diff --git a/cmd/capi/main.go b/cmd/capi/main.go index 7aad4d7..0761ae3 100644 --- a/cmd/capi/main.go +++ b/cmd/capi/main.go @@ -2517,6 +2517,8 @@ func (s *Server) bulkUpdateUsers(c *gin.Context) { return } + // An empty group id clears the assignment, matching the single-user patch. + groupID := strings.TrimSpace(body.Value) switch body.Action { case "set_status": if !allowedString(body.Value, "active", "disabled", "limited", "overdue") { @@ -2536,6 +2538,11 @@ func (s *Server) bulkUpdateUsers(c *gin.Context) { validationError(c, "至少需要保留一个启用的管理员") return } + case "set_group": + if groupID != "" && s.findUserGroup(groupID) == nil { + validationError(c, "用户分组不存在") + return + } case "adjust_balance": if body.Amount == 0 || body.Amount < -1_000_000_000 || body.Amount > 1_000_000_000 { validationError(c, "额度调整值必须非零,且在允许范围内") @@ -2565,6 +2572,8 @@ func (s *Server) bulkUpdateUsers(c *gin.Context) { case "set_role": user.Role = body.Value s.syncAccountAccessLocked(user) + case "set_group": + user.GroupID = groupID case "adjust_balance": user.Balance = round4(user.Balance + body.Amount) s.state.QuotaLedger = append(s.state.QuotaLedger, QuotaEntry{ diff --git a/cmd/capi/main_test.go b/cmd/capi/main_test.go index bb0d50c..7b0f261 100644 --- a/cmd/capi/main_test.go +++ b/cmd/capi/main_test.go @@ -4918,3 +4918,129 @@ func TestIsImmutableBuildAsset(t *testing.T) { } } } + +func TestBulkSetGroupAssignsAndClears(t *testing.T) { + withEnv(t, map[string]string{"PERSISTENCE": "memory"}) + server, router := testServerRouter(t) + seedGatewayFixtures(server) + + created := perform(router, http.MethodPost, "/api/groups", `{"name":"bulk_group","description":"批量"}`, nil) + if created.Code != http.StatusCreated { + t.Fatalf("create group status = %d body = %s", created.Code, created.Body.String()) + } + var groupPayload struct { + Group UserGroup `json:"group"` + } + if err := json.Unmarshal(created.Body.Bytes(), &groupPayload); err != nil { + t.Fatalf("decode group: %v", err) + } + groupID := groupPayload.Group.ID + + // An unknown group must be rejected before anything is written. + unknown := perform(router, http.MethodPost, "/api/users/bulk", `{"userIds":["usr_1002"],"action":"set_group","value":"grp_missing"}`, nil) + if unknown.Code != http.StatusBadRequest { + t.Fatalf("unknown group bulk status = %d body = %s", unknown.Code, unknown.Body.String()) + } + + assigned := perform(router, http.MethodPost, "/api/users/bulk", `{"userIds":["usr_1002","usr_1003"],"action":"set_group","value":"`+groupID+`"}`, nil) + if assigned.Code != http.StatusOK { + t.Fatalf("bulk set_group status = %d body = %s", assigned.Code, assigned.Body.String()) + } + if !bytes.Contains(assigned.Body.Bytes(), []byte(`"groupId":"`+groupID+`"`)) { + t.Fatalf("bulk set_group response missing group id: %s", assigned.Body.String()) + } + + server.mu.Lock() + for _, id := range []string{"usr_1002", "usr_1003"} { + if user := server.findUser(id); user == nil || user.GroupID != groupID { + server.mu.Unlock() + t.Fatalf("user %s group after bulk assign = %#v", id, user) + } + } + server.mu.Unlock() + + // An empty value clears the assignment, matching the single-user patch. + cleared := perform(router, http.MethodPost, "/api/users/bulk", `{"userIds":["usr_1002"],"action":"set_group","value":""}`, nil) + if cleared.Code != http.StatusOK { + t.Fatalf("bulk clear group status = %d body = %s", cleared.Code, cleared.Body.String()) + } + server.mu.Lock() + defer server.mu.Unlock() + if user := server.findUser("usr_1002"); user == nil || user.GroupID != "" { + t.Fatalf("user group after bulk clear = %#v", user) + } + if user := server.findUser("usr_1003"); user == nil || user.GroupID != groupID { + t.Fatalf("unselected user should keep its group: %#v", user) + } +} + +func TestDefaultRegistrationGroupAppliesToNewUsers(t *testing.T) { + withEnv(t, map[string]string{"PERSISTENCE": "memory"}) + server, router := testServerRouter(t) + + setup := perform(router, http.MethodPost, "/api/auth/setup", `{ + "username":"root_admin", + "password":"correct-horse-battery", + "displayName":"Root Admin", + "email":"root@example.test", + "registrationEnabled":false, + "registrationMode":"username" + }`, nil) + if setup.Code != http.StatusCreated { + t.Fatalf("setup status = %d body = %s", setup.Code, setup.Body.String()) + } + + created := perform(router, http.MethodPost, "/api/groups", `{"name":"newcomers","description":"新用户"}`, nil) + if created.Code != http.StatusCreated { + t.Fatalf("create group status = %d body = %s", created.Code, created.Body.String()) + } + var groupPayload struct { + Group UserGroup `json:"group"` + } + if err := json.Unmarshal(created.Body.Bytes(), &groupPayload); err != nil { + t.Fatalf("decode group: %v", err) + } + groupID := groupPayload.Group.ID + + // The default group is reported back and persisted. + settings := perform(router, http.MethodGet, "/api/settings/auth", "", nil) + if settings.Code != http.StatusOK || !bytes.Contains(settings.Body.Bytes(), []byte(`"defaultGroupId"`)) { + t.Fatalf("auth settings status = %d body = %s", settings.Code, settings.Body.String()) + } + updated := perform(router, http.MethodPatch, "/api/settings/auth", `{"registrationEnabled":true,"defaultGroupId":"`+groupID+`"}`, nil) + if updated.Code != http.StatusOK || !bytes.Contains(updated.Body.Bytes(), []byte(`"defaultGroupId":"`+groupID+`"`)) { + t.Fatalf("update default group status = %d body = %s", updated.Code, updated.Body.String()) + } + + // An unknown default group must be rejected. + badDefault := perform(router, http.MethodPatch, "/api/settings/auth", `{"registrationEnabled":true,"defaultGroupId":"grp_missing"}`, nil) + if badDefault.Code != http.StatusBadRequest { + t.Fatalf("unknown default group status = %d body = %s", badDefault.Code, badDefault.Body.String()) + } + + register := perform(router, http.MethodPost, "/api/auth/register", `{ + "username":"newcomer", + "password":"safe-password-123", + "displayName":"Newcomer", + "email":"newcomer@example.test" + }`, nil) + if register.Code != http.StatusCreated { + t.Fatalf("register status = %d body = %s", register.Code, register.Body.String()) + } + + server.mu.Lock() + defer server.mu.Unlock() + var registered *User + for i := range server.state.Users { + if strings.EqualFold(server.state.Users[i].Email, "newcomer@example.test") { + registered = &server.state.Users[i] + break + } + } + if registered == nil { + t.Fatal("registered user not found") + } + if registered.GroupID != groupID { + t.Fatalf("new user group = %q, want %q", registered.GroupID, groupID) + } +} diff --git a/dist/assets/index-BW0kmUgI.js b/dist/assets/index-BW0kmUgI.js new file mode 100644 index 0000000..31ccc72 --- /dev/null +++ b/dist/assets/index-BW0kmUgI.js @@ -0,0 +1,43 @@ +(function(){const m=document.createElement("link").relList;if(m&&m.supports&&m.supports("modulepreload"))return;for(const E of document.querySelectorAll('link[rel="modulepreload"]'))r(E);new MutationObserver(E=>{for(const O of E)if(O.type==="childList")for(const K of O.addedNodes)K.tagName==="LINK"&&K.rel==="modulepreload"&&r(K)}).observe(document,{childList:!0,subtree:!0});function y(E){const O={};return E.integrity&&(O.integrity=E.integrity),E.referrerPolicy&&(O.referrerPolicy=E.referrerPolicy),E.crossOrigin==="use-credentials"?O.credentials="include":E.crossOrigin==="anonymous"?O.credentials="omit":O.credentials="same-origin",O}function r(E){if(E.ep)return;E.ep=!0;const O=y(E);fetch(E.href,O)}})();function H0(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var Xc={exports:{}},ii={};var em;function w0(){if(em)return ii;em=1;var c=Symbol.for("react.transitional.element"),m=Symbol.for("react.fragment");function y(r,E,O){var K=null;if(O!==void 0&&(K=""+O),E.key!==void 0&&(K=""+E.key),"key"in E){O={};for(var P in E)P!=="key"&&(O[P]=E[P])}else O=E;return E=O.ref,{$$typeof:c,type:r,key:K,ref:E!==void 0?E:null,props:O}}return ii.Fragment=m,ii.jsx=y,ii.jsxs=y,ii}var tm;function B0(){return tm||(tm=1,Xc.exports=w0()),Xc.exports}var n=B0(),Kc={exports:{}},Ae={};var lm;function q0(){if(lm)return Ae;lm=1;var c=Symbol.for("react.transitional.element"),m=Symbol.for("react.portal"),y=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),O=Symbol.for("react.consumer"),K=Symbol.for("react.context"),P=Symbol.for("react.forward_ref"),T=Symbol.for("react.suspense"),b=Symbol.for("react.memo"),G=Symbol.for("react.lazy"),_=Symbol.for("react.activity"),ae=Symbol.iterator;function te(f){return f===null||typeof f!="object"?null:(f=ae&&f[ae]||f["@@iterator"],typeof f=="function"?f:null)}var de={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},le=Object.assign,ne={};function ie(f,N,q){this.props=f,this.context=N,this.refs=ne,this.updater=q||de}ie.prototype.isReactComponent={},ie.prototype.setState=function(f,N){if(typeof f!="object"&&typeof f!="function"&&f!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,f,N,"setState")},ie.prototype.forceUpdate=function(f){this.updater.enqueueForceUpdate(this,f,"forceUpdate")};function ge(){}ge.prototype=ie.prototype;function me(f,N,q){this.props=f,this.context=N,this.refs=ne,this.updater=q||de}var Ce=me.prototype=new ge;Ce.constructor=me,le(Ce,ie.prototype),Ce.isPureReactComponent=!0;var F=Array.isArray;function ve(){}var D={H:null,A:null,T:null,S:null},ee=Object.prototype.hasOwnProperty;function oe(f,N,q){var L=q.ref;return{$$typeof:c,type:f,key:N,ref:L!==void 0?L:null,props:q}}function Ne(f,N){return oe(f.type,N,f.props)}function Me(f){return typeof f=="object"&&f!==null&&f.$$typeof===c}function ue(f){var N={"=":"=0",":":"=2"};return"$"+f.replace(/[=:]/g,function(q){return N[q]})}var Q=/\/+/g;function re(f,N){return typeof f=="object"&&f!==null&&f.key!=null?ue(""+f.key):N.toString(36)}function V(f){switch(f.status){case"fulfilled":return f.value;case"rejected":throw f.reason;default:switch(typeof f.status=="string"?f.then(ve,ve):(f.status="pending",f.then(function(N){f.status==="pending"&&(f.status="fulfilled",f.value=N)},function(N){f.status==="pending"&&(f.status="rejected",f.reason=N)})),f.status){case"fulfilled":return f.value;case"rejected":throw f.reason}}throw f}function A(f,N,q,L,Z){var xe=typeof f;(xe==="undefined"||xe==="boolean")&&(f=null);var M=!1;if(f===null)M=!0;else switch(xe){case"bigint":case"string":case"number":M=!0;break;case"object":switch(f.$$typeof){case c:case m:M=!0;break;case G:return M=f._init,A(M(f._payload),N,q,L,Z)}}if(M)return Z=Z(f),M=L===""?"."+re(f,0):L,F(Z)?(q="",M!=null&&(q=M.replace(Q,"$&/")+"/"),A(Z,N,q,"",function(ot){return ot})):Z!=null&&(Me(Z)&&(Z=Ne(Z,q+(Z.key==null||f&&f.key===Z.key?"":(""+Z.key).replace(Q,"$&/")+"/")+M)),N.push(Z)),1;M=0;var je=L===""?".":L+":";if(F(f))for(var Se=0;Se>>1,$=A[z];if(0>>1;zE(q,p))L<$&&0>E(Z,q)?(A[z]=Z,A[L]=p,z=L):(A[z]=q,A[N]=p,z=N);else if(L<$&&0>E(Z,p))A[z]=Z,A[L]=p,z=L;else break e}}return Y}function E(A,Y){var p=A.sortIndex-Y.sortIndex;return p!==0?p:A.id-Y.id}if(c.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var O=performance;c.unstable_now=function(){return O.now()}}else{var K=Date,P=K.now();c.unstable_now=function(){return K.now()-P}}var T=[],b=[],G=1,_=null,ae=3,te=!1,de=!1,le=!1,ne=!1,ie=typeof setTimeout=="function"?setTimeout:null,ge=typeof clearTimeout=="function"?clearTimeout:null,me=typeof setImmediate<"u"?setImmediate:null;function Ce(A){for(var Y=y(b);Y!==null;){if(Y.callback===null)r(b);else if(Y.startTime<=A)r(b),Y.sortIndex=Y.expirationTime,m(T,Y);else break;Y=y(b)}}function F(A){if(le=!1,Ce(A),!de)if(y(T)!==null)de=!0,ve||(ve=!0,ue());else{var Y=y(b);Y!==null&&V(F,Y.startTime-A)}}var ve=!1,D=-1,ee=5,oe=-1;function Ne(){return ne?!0:!(c.unstable_now()-oeA&&Ne());){var z=_.callback;if(typeof z=="function"){_.callback=null,ae=_.priorityLevel;var $=z(_.expirationTime<=A);if(A=c.unstable_now(),typeof $=="function"){_.callback=$,Ce(A),Y=!0;break t}_===y(T)&&r(T),Ce(A)}else r(T);_=y(T)}if(_!==null)Y=!0;else{var f=y(b);f!==null&&V(F,f.startTime-A),Y=!1}}break e}finally{_=null,ae=p,te=!1}Y=void 0}}finally{Y?ue():ve=!1}}}var ue;if(typeof me=="function")ue=function(){me(Me)};else if(typeof MessageChannel<"u"){var Q=new MessageChannel,re=Q.port2;Q.port1.onmessage=Me,ue=function(){re.postMessage(null)}}else ue=function(){ie(Me,0)};function V(A,Y){D=ie(function(){A(c.unstable_now())},Y)}c.unstable_IdlePriority=5,c.unstable_ImmediatePriority=1,c.unstable_LowPriority=4,c.unstable_NormalPriority=3,c.unstable_Profiling=null,c.unstable_UserBlockingPriority=2,c.unstable_cancelCallback=function(A){A.callback=null},c.unstable_forceFrameRate=function(A){0>A||125z?(A.sortIndex=p,m(b,A),y(T)===null&&A===y(b)&&(le?(ge(D),D=-1):le=!0,V(F,p-z))):(A.sortIndex=$,m(T,A),de||te||(de=!0,ve||(ve=!0,ue()))),A},c.unstable_shouldYield=Ne,c.unstable_wrapCallback=function(A){var Y=ae;return function(){var p=ae;ae=Y;try{return A.apply(this,arguments)}finally{ae=p}}}})(Vc)),Vc}var im;function L0(){return im||(im=1,kc.exports=Y0()),kc.exports}var Jc={exports:{}},xt={};var sm;function Q0(){if(sm)return xt;sm=1;var c=Pc();function m(T){var b="https://react.dev/errors/"+T;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(m){console.error(m)}}return c(),Jc.exports=Q0(),Jc.exports}var cm;function K0(){if(cm)return si;cm=1;var c=L0(),m=Pc(),y=X0();function r(e){var t="https://react.dev/errors/"+e;if(1$||(e.current=z[$],z[$]=null,$--)}function q(e,t){$++,z[$]=e.current,e.current=t}var L=f(null),Z=f(null),xe=f(null),M=f(null);function je(e,t){switch(q(xe,t),q(Z,e),q(L,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Nf(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Nf(t),e=Af(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}N(L),q(L,e)}function Se(){N(L),N(Z),N(xe)}function ot(e){e.memoizedState!==null&&q(M,e);var t=L.current,l=Af(t,e.type);t!==l&&(q(Z,e),q(L,l))}function J(e){Z.current===e&&(N(L),N(Z)),M.current===e&&(N(M),ti._currentValue=p)}var Je,ut;function Ie(e){if(Je===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);Je=t&&t[1]||"",ut=-1)":-1i||d[a]!==j[i]){var U=` +`+d[a].replace(" at new "," at ");return e.displayName&&U.includes("")&&(U=U.replace("",e.displayName)),U}while(1<=a&&0<=i);break}}}finally{tl=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Ie(l):""}function mt(e,t){switch(e.tag){case 26:case 27:case 5:return Ie(e.type);case 16:return Ie("Lazy");case 13:return e.child!==t&&t!==null?Ie("Suspense Fallback"):Ie("Suspense");case 19:return Ie("SuspenseList");case 0:case 15:return k(e.type,!1);case 11:return k(e.type.render,!1);case 1:return k(e.type,!0);case 31:return Ie("Activity");default:return""}}function Ut(e){try{var t="",l=null;do t+=mt(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var R=Object.prototype.hasOwnProperty,Ue=c.unstable_scheduleCallback,rt=c.unstable_cancelCallback,jt=c.unstable_shouldYield,ht=c.unstable_requestPaint,Pe=c.unstable_now,zs=c.unstable_getCurrentPriorityLevel,mn=c.unstable_ImmediatePriority,na=c.unstable_UserBlockingPriority,ia=c.unstable_NormalPriority,Os=c.unstable_LowPriority,H=c.unstable_IdlePriority,X=c.log,I=c.unstable_setDisableYieldValue,W=null,he=null;function qe(e){if(typeof X=="function"&&I(e),he&&typeof he.setStrictMode=="function")try{he.setStrictMode(W,e)}catch{}}var Ze=Math.clz32?Math.clz32:sa,Rt=Math.log,Dl=Math.LN2;function sa(e){return e>>>=0,e===0?32:31-(Rt(e)/Dl|0)|0}var Ta=256,Ea=262144,Ul=4194304;function fl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function oi(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var i=0,s=e.suspendedLanes,u=e.pingedLanes;e=e.warmLanes;var o=a&134217727;return o!==0?(a=o&~s,a!==0?i=fl(a):(u&=o,u!==0?i=fl(u):l||(l=o&~e,l!==0&&(i=fl(l))))):(o=a&~s,o!==0?i=fl(o):u!==0?i=fl(u):l||(l=a&~e,l!==0&&(i=fl(l)))),i===0?0:t!==0&&t!==i&&(t&s)===0&&(s=i&-i,l=t&-t,s>=l||s===32&&(l&4194048)!==0)?t:i}function hn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Sm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function lo(){var e=Ul;return Ul<<=1,(Ul&62914560)===0&&(Ul=4194304),e}function _s(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function pn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Nm(e,t,l,a,i,s){var u=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var o=e.entanglements,d=e.expirationTimes,j=e.hiddenUpdates;for(l=u&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var zm=/[\n"\\]/g;function Kt(e){return e.replace(zm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Bs(e,t,l,a,i,s,u,o){e.name="",u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"?e.type=u:e.removeAttribute("type"),t!=null?u==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+Xt(t)):e.value!==""+Xt(t)&&(e.value=""+Xt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?qs(e,u,Xt(t)):l!=null?qs(e,u,Xt(l)):a!=null&&e.removeAttribute("value"),i==null&&s!=null&&(e.defaultChecked=!!s),i!=null&&(e.checked=i&&typeof i!="function"&&typeof i!="symbol"),o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.name=""+Xt(o):e.removeAttribute("name")}function vo(e,t,l,a,i,s,u,o){if(s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"&&(e.type=s),t!=null||l!=null){if(!(s!=="submit"&&s!=="reset"||t!=null)){ws(e);return}l=l!=null?""+Xt(l):"",t=t!=null?""+Xt(t):l,o||t===e.value||(e.value=t),e.defaultValue=t}a=a??i,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=o?e.checked:!!a,e.defaultChecked=!!a,u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.name=u),ws(e)}function qs(e,t,l){t==="number"&&fi(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ua(e,t,l,a){if(e=e.options,t){t={};for(var i=0;i"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Xs=!1;if(pl)try{var gn={};Object.defineProperty(gn,"passive",{get:function(){Xs=!0}}),window.addEventListener("test",gn,gn),window.removeEventListener("test",gn,gn)}catch{Xs=!1}var Hl=null,Ks=null,hi=null;function No(){if(hi)return hi;var e,t=Ks,l=t.length,a,i="value"in Hl?Hl.value:Hl.textContent,s=i.length;for(e=0;e=Sn),zo=" ",Oo=!1;function _o(e,t){switch(e){case"keyup":return ah.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Do(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ba=!1;function ih(e,t){switch(e){case"compositionend":return Do(t);case"keypress":return t.which!==32?null:(Oo=!0,zo);case"textInput":return e=t.data,e===zo&&Oo?null:e;default:return null}}function sh(e,t){if(Ba)return e==="compositionend"||!$s&&_o(e,t)?(e=No(),hi=Ks=Hl=null,Ba=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Yo(l)}}function Qo(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Qo(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Xo(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=fi(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=fi(e.document)}return t}function Is(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var hh=pl&&"documentMode"in document&&11>=document.documentMode,qa=null,Ps=null,Tn=null,eu=!1;function Ko(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;eu||qa==null||qa!==fi(a)||(a=qa,"selectionStart"in a&&Is(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Tn&&Cn(Tn,a)||(Tn=a,a=us(Ps,"onSelect"),0>=u,i-=u,cl=1<<32-Ze(t)+i|l<Ee?(De=ce,ce=null):De=ce.sibling;var we=S(v,ce,x[Ee],w);if(we===null){ce===null&&(ce=De);break}e&&ce&&we.alternate===null&&t(v,ce),h=s(we,h,Ee),He===null?fe=we:He.sibling=we,He=we,ce=De}if(Ee===x.length)return l(v,ce),Re&&yl(v,Ee),fe;if(ce===null){for(;EeEe?(De=ce,ce=null):De=ce.sibling;var aa=S(v,ce,we.value,w);if(aa===null){ce===null&&(ce=De);break}e&&ce&&aa.alternate===null&&t(v,ce),h=s(aa,h,Ee),He===null?fe=aa:He.sibling=aa,He=aa,ce=De}if(we.done)return l(v,ce),Re&&yl(v,Ee),fe;if(ce===null){for(;!we.done;Ee++,we=x.next())we=B(v,we.value,w),we!==null&&(h=s(we,h,Ee),He===null?fe=we:He.sibling=we,He=we);return Re&&yl(v,Ee),fe}for(ce=a(ce);!we.done;Ee++,we=x.next())we=C(ce,v,Ee,we.value,w),we!==null&&(e&&we.alternate!==null&&ce.delete(we.key===null?Ee:we.key),h=s(we,h,Ee),He===null?fe=we:He.sibling=we,He=we);return e&&ce.forEach(function(R0){return t(v,R0)}),Re&&yl(v,Ee),fe}function Xe(v,h,x,w){if(typeof x=="object"&&x!==null&&x.type===le&&x.key===null&&(x=x.props.children),typeof x=="object"&&x!==null){switch(x.$$typeof){case te:e:{for(var fe=x.key;h!==null;){if(h.key===fe){if(fe=x.type,fe===le){if(h.tag===7){l(v,h.sibling),w=i(h,x.props.children),w.return=v,v=w;break e}}else if(h.elementType===fe||typeof fe=="object"&&fe!==null&&fe.$$typeof===ee&&ya(fe)===h.type){l(v,h.sibling),w=i(h,x.props),Dn(w,x),w.return=v,v=w;break e}l(v,h);break}else t(v,h);h=h.sibling}x.type===le?(w=fa(x.props.children,v.mode,w,x.key),w.return=v,v=w):(w=Ai(x.type,x.key,x.props,null,v.mode,w),Dn(w,x),w.return=v,v=w)}return u(v);case de:e:{for(fe=x.key;h!==null;){if(h.key===fe)if(h.tag===4&&h.stateNode.containerInfo===x.containerInfo&&h.stateNode.implementation===x.implementation){l(v,h.sibling),w=i(h,x.children||[]),w.return=v,v=w;break e}else{l(v,h);break}else t(v,h);h=h.sibling}w=uu(x,v.mode,w),w.return=v,v=w}return u(v);case ee:return x=ya(x),Xe(v,h,x,w)}if(V(x))return se(v,h,x,w);if(ue(x)){if(fe=ue(x),typeof fe!="function")throw Error(r(150));return x=fe.call(x),ye(v,h,x,w)}if(typeof x.then=="function")return Xe(v,h,_i(x),w);if(x.$$typeof===me)return Xe(v,h,Ei(v,x),w);Di(v,x)}return typeof x=="string"&&x!==""||typeof x=="number"||typeof x=="bigint"?(x=""+x,h!==null&&h.tag===6?(l(v,h.sibling),w=i(h,x),w.return=v,v=w):(l(v,h),w=su(x,v.mode,w),w.return=v,v=w),u(v)):l(v,h)}return function(v,h,x,w){try{_n=0;var fe=Xe(v,h,x,w);return $a=null,fe}catch(ce){if(ce===Ja||ce===zi)throw ce;var He=wt(29,ce,null,v.mode);return He.lanes=w,He.return=v,He}}}var ga=mr(!0),hr=mr(!1),Yl=!1;function gu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xu(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ll(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ql(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(Be&2)!==0){var i=a.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),a.pending=t,t=Ni(e),Fo(e,null,l),t}return Si(e,a,t,l),Ni(e)}function Un(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,no(e,l)}}function ju(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var i=null,s=null;if(l=l.firstBaseUpdate,l!==null){do{var u={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};s===null?i=s=u:s=s.next=u,l=l.next}while(l!==null);s===null?i=s=t:s=s.next=t}else i=s=t;l={baseState:a.baseState,firstBaseUpdate:i,lastBaseUpdate:s,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Su=!1;function Rn(){if(Su){var e=Va;if(e!==null)throw e}}function Hn(e,t,l,a){Su=!1;var i=e.updateQueue;Yl=!1;var s=i.firstBaseUpdate,u=i.lastBaseUpdate,o=i.shared.pending;if(o!==null){i.shared.pending=null;var d=o,j=d.next;d.next=null,u===null?s=j:u.next=j,u=d;var U=e.alternate;U!==null&&(U=U.updateQueue,o=U.lastBaseUpdate,o!==u&&(o===null?U.firstBaseUpdate=j:o.next=j,U.lastBaseUpdate=d))}if(s!==null){var B=i.baseState;u=0,U=j=d=null,o=s;do{var S=o.lane&-536870913,C=S!==o.lane;if(C?(_e&S)===S:(a&S)===S){S!==0&&S===ka&&(Su=!0),U!==null&&(U=U.next={lane:0,tag:o.tag,payload:o.payload,callback:null,next:null});e:{var se=e,ye=o;S=t;var Xe=l;switch(ye.tag){case 1:if(se=ye.payload,typeof se=="function"){B=se.call(Xe,B,S);break e}B=se;break e;case 3:se.flags=se.flags&-65537|128;case 0:if(se=ye.payload,S=typeof se=="function"?se.call(Xe,B,S):se,S==null)break e;B=_({},B,S);break e;case 2:Yl=!0}}S=o.callback,S!==null&&(e.flags|=64,C&&(e.flags|=8192),C=i.callbacks,C===null?i.callbacks=[S]:C.push(S))}else C={lane:S,tag:o.tag,payload:o.payload,callback:o.callback,next:null},U===null?(j=U=C,d=B):U=U.next=C,u|=S;if(o=o.next,o===null){if(o=i.shared.pending,o===null)break;C=o,o=C.next,C.next=null,i.lastBaseUpdate=C,i.shared.pending=null}}while(!0);U===null&&(d=B),i.baseState=d,i.firstBaseUpdate=j,i.lastBaseUpdate=U,s===null&&(i.shared.lanes=0),Vl|=u,e.lanes=u,e.memoizedState=B}}function pr(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function vr(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;es?s:8;var u=A.T,o={};A.T=o,Lu(e,!1,t,l);try{var d=i(),j=A.S;if(j!==null&&j(o,d),d!==null&&typeof d=="object"&&typeof d.then=="function"){var U=Nh(d,a);qn(e,t,U,Lt(e))}else qn(e,t,a,Lt(e))}catch(B){qn(e,t,{then:function(){},status:"rejected",reason:B},Lt())}finally{Y.p=s,u!==null&&o.types!==null&&(u.types=o.types),A.T=u}}function zh(){}function Gu(e,t,l,a){if(e.tag!==5)throw Error(r(476));var i=Jr(e).queue;Vr(e,i,t,p,l===null?zh:function(){return $r(e),l(a)})}function Jr(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:p,baseState:p,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jl,lastRenderedState:p},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function $r(e){var t=Jr(e);t.next===null&&(t=e.alternate.memoizedState),qn(e,t.next.queue,{},Lt())}function Yu(){return yt(ti)}function Wr(){return tt().memoizedState}function Fr(){return tt().memoizedState}function Oh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Lt();e=Ll(l);var a=Ql(t,e,l);a!==null&&(zt(a,t,l),Un(a,t,l)),t={cache:pu()},e.payload=t;return}t=t.return}}function _h(e,t,l){var a=Lt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Qi(e)?Pr(t,l):(l=nu(e,t,l,a),l!==null&&(zt(l,e,a),ed(l,t,a)))}function Ir(e,t,l){var a=Lt();qn(e,t,l,a)}function qn(e,t,l,a){var i={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Qi(e))Pr(t,i);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var u=t.lastRenderedState,o=s(u,l);if(i.hasEagerState=!0,i.eagerState=o,Ht(o,u))return Si(e,t,i,0),Ke===null&&ji(),!1}catch{}if(l=nu(e,t,i,a),l!==null)return zt(l,e,a),ed(l,t,a),!0}return!1}function Lu(e,t,l,a){if(a={lane:2,revertLane:gc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Qi(e)){if(t)throw Error(r(479))}else t=nu(e,l,a,2),t!==null&&zt(t,e,2)}function Qi(e){var t=e.alternate;return e===Te||t!==null&&t===Te}function Pr(e,t){Fa=Hi=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function ed(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,no(e,l)}}var Gn={readContext:yt,use:qi,useCallback:We,useContext:We,useEffect:We,useImperativeHandle:We,useLayoutEffect:We,useInsertionEffect:We,useMemo:We,useReducer:We,useRef:We,useState:We,useDebugValue:We,useDeferredValue:We,useTransition:We,useSyncExternalStore:We,useId:We,useHostTransitionStatus:We,useFormState:We,useActionState:We,useOptimistic:We,useMemoCache:We,useCacheRefresh:We};Gn.useEffectEvent=We;var td={readContext:yt,use:qi,useCallback:function(e,t){return St().memoizedState=[e,t===void 0?null:t],e},useContext:yt,useEffect:qr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Yi(4194308,4,Qr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Yi(4194308,4,e,t)},useInsertionEffect:function(e,t){Yi(4,2,e,t)},useMemo:function(e,t){var l=St();t=t===void 0?null:t;var a=e();if(xa){qe(!0);try{e()}finally{qe(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=St();if(l!==void 0){var i=l(t);if(xa){qe(!0);try{l(t)}finally{qe(!1)}}}else i=t;return a.memoizedState=a.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},a.queue=e,e=e.dispatch=_h.bind(null,Te,e),[a.memoizedState,e]},useRef:function(e){var t=St();return e={current:e},t.memoizedState=e},useState:function(e){e=Ru(e);var t=e.queue,l=Ir.bind(null,Te,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Bu,useDeferredValue:function(e,t){var l=St();return qu(l,e,t)},useTransition:function(){var e=Ru(!1);return e=Vr.bind(null,Te,e.queue,!0,!1),St().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=Te,i=St();if(Re){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Ke===null)throw Error(r(349));(_e&127)!==0||Sr(a,t,l)}i.memoizedState=l;var s={value:l,getSnapshot:t};return i.queue=s,qr(Ar.bind(null,a,s,e),[e]),a.flags|=2048,Pa(9,{destroy:void 0},Nr.bind(null,a,s,l,t),null),l},useId:function(){var e=St(),t=Ke.identifierPrefix;if(Re){var l=ol,a=cl;l=(a&~(1<<32-Ze(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=wi++,0<\/script>",s=s.removeChild(s.firstChild);break;case"select":s=typeof a.is=="string"?u.createElement("select",{is:a.is}):u.createElement("select"),a.multiple?s.multiple=!0:a.size&&(s.size=a.size);break;default:s=typeof a.is=="string"?u.createElement(i,{is:a.is}):u.createElement(i)}}s[pt]=t,s[Nt]=a;e:for(u=t.child;u!==null;){if(u.tag===5||u.tag===6)s.appendChild(u.stateNode);else if(u.tag!==4&&u.tag!==27&&u.child!==null){u.child.return=u,u=u.child;continue}if(u===t)break e;for(;u.sibling===null;){if(u.return===null||u.return===t)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}t.stateNode=s;e:switch(gt(s,i,a),i){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Nl(t)}}return Ve(t),tc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Nl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=xe.current,Ka(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,i=vt,i!==null)switch(i.tag){case 27:case 5:a=i.memoizedProps}e[pt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||jf(e.nodeValue,l)),e||ql(t,!0)}else e=cs(e).createTextNode(a),e[pt]=t,t.stateNode=e}return Ve(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Ka(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[pt]=t}else ma(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),e=!1}else l=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(qt(t),t):(qt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Ve(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Ka(t),a!==null&&a.dehydrated!==null){if(e===null){if(!i)throw Error(r(318));if(i=t.memoizedState,i=i!==null?i.dehydrated:null,!i)throw Error(r(317));i[pt]=t}else ma(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),i=!1}else i=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(qt(t),t):(qt(t),null)}return qt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,i=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(i=a.alternate.memoizedState.cachePool.pool),s=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(s=a.memoizedState.cachePool.pool),s!==i&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Vi(t,t.updateQueue),Ve(t),null);case 4:return Se(),e===null&&Nc(t.stateNode.containerInfo),Ve(t),null;case 10:return gl(t.type),Ve(t),null;case 19:if(N(et),a=t.memoizedState,a===null)return Ve(t),null;if(i=(t.flags&128)!==0,s=a.rendering,s===null)if(i)Ln(a,!1);else{if(Fe!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(s=Ri(e),s!==null){for(t.flags|=128,Ln(a,!1),e=s.updateQueue,t.updateQueue=e,Vi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Io(l,e),l=l.sibling;return q(et,et.current&1|2),Re&&yl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&Pe()>Ii&&(t.flags|=128,i=!0,Ln(a,!1),t.lanes=4194304)}else{if(!i)if(e=Ri(s),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Vi(t,e),Ln(a,!0),a.tail===null&&a.tailMode==="hidden"&&!s.alternate&&!Re)return Ve(t),null}else 2*Pe()-a.renderingStartTime>Ii&&l!==536870912&&(t.flags|=128,i=!0,Ln(a,!1),t.lanes=4194304);a.isBackwards?(s.sibling=t.child,t.child=s):(e=a.last,e!==null?e.sibling=s:t.child=s,a.last=s)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=Pe(),e.sibling=null,l=et.current,q(et,i?l&1|2:l&1),Re&&yl(t,a.treeForkCount),e):(Ve(t),null);case 22:case 23:return qt(t),Au(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Ve(t),t.subtreeFlags&6&&(t.flags|=8192)):Ve(t),l=t.updateQueue,l!==null&&Vi(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&N(va),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),gl(at),Ve(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function wh(e,t){switch(ou(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return gl(at),Se(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return J(t),null;case 31:if(t.memoizedState!==null){if(qt(t),t.alternate===null)throw Error(r(340));ma()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(qt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));ma()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return N(et),null;case 4:return Se(),null;case 10:return gl(t.type),null;case 22:case 23:return qt(t),Au(),e!==null&&N(va),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return gl(at),null;case 25:return null;default:return null}}function Cd(e,t){switch(ou(t),t.tag){case 3:gl(at),Se();break;case 26:case 27:case 5:J(t);break;case 4:Se();break;case 31:t.memoizedState!==null&&qt(t);break;case 13:qt(t);break;case 19:N(et);break;case 10:gl(t.type);break;case 22:case 23:qt(t),Au(),e!==null&&N(va);break;case 24:gl(at)}}function Qn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var i=a.next;l=i;do{if((l.tag&e)===e){a=void 0;var s=l.create,u=l.inst;a=s(),u.destroy=a}l=l.next}while(l!==i)}}catch(o){Ye(t,t.return,o)}}function Zl(e,t,l){try{var a=t.updateQueue,i=a!==null?a.lastEffect:null;if(i!==null){var s=i.next;a=s;do{if((a.tag&e)===e){var u=a.inst,o=u.destroy;if(o!==void 0){u.destroy=void 0,i=t;var d=l,j=o;try{j()}catch(U){Ye(i,d,U)}}}a=a.next}while(a!==s)}}catch(U){Ye(t,t.return,U)}}function Td(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{vr(t,l)}catch(a){Ye(e,e.return,a)}}}function Ed(e,t,l){l.props=ja(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ye(e,t,a)}}function Xn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(i){Ye(e,t,i)}}function rl(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(i){Ye(e,t,i)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(i){Ye(e,t,i)}else l.current=null}function Md(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(i){Ye(e,e.return,i)}}function lc(e,t,l){try{var a=e.stateNode;n0(a,e.type,l,t),a[Nt]=t}catch(i){Ye(e,e.return,i)}}function zd(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Il(e.type)||e.tag===4}function ac(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||zd(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Il(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function nc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=hl));else if(a!==4&&(a===27&&Il(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(nc(e,t,l),e=e.sibling;e!==null;)nc(e,t,l),e=e.sibling}function Ji(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Il(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Ji(e,t,l),e=e.sibling;e!==null;)Ji(e,t,l),e=e.sibling}function Od(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);gt(t,a,l),t[pt]=e,t[Nt]=l}catch(s){Ye(e,e.return,s)}}var Al=!1,st=!1,ic=!1,_d=typeof WeakSet=="function"?WeakSet:Set,ft=null;function Bh(e,t){if(e=e.containerInfo,Tc=ps,e=Xo(e),Is(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var i=a.anchorOffset,s=a.focusNode;a=a.focusOffset;try{l.nodeType,s.nodeType}catch{l=null;break e}var u=0,o=-1,d=-1,j=0,U=0,B=e,S=null;t:for(;;){for(var C;B!==l||i!==0&&B.nodeType!==3||(o=u+i),B!==s||a!==0&&B.nodeType!==3||(d=u+a),B.nodeType===3&&(u+=B.nodeValue.length),(C=B.firstChild)!==null;)S=B,B=C;for(;;){if(B===e)break t;if(S===l&&++j===i&&(o=u),S===s&&++U===a&&(d=u),(C=B.nextSibling)!==null)break;B=S,S=B.parentNode}B=C}l=o===-1||d===-1?null:{start:o,end:d}}else l=null}l=l||{start:0,end:0}}else l=null;for(Ec={focusedElem:e,selectionRange:l},ps=!1,ft=t;ft!==null;)if(t=ft,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ft=e;else for(;ft!==null;){switch(t=ft,s=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),gt(s,a,l),s[pt]=e,dt(s),a=s;break e;case"link":var u=qf("link","href",i).get(a+(l.href||""));if(u){for(var o=0;oXe&&(u=Xe,Xe=ye,ye=u);var v=Lo(o,ye),h=Lo(o,Xe);if(v&&h&&(C.rangeCount!==1||C.anchorNode!==v.node||C.anchorOffset!==v.offset||C.focusNode!==h.node||C.focusOffset!==h.offset)){var x=B.createRange();x.setStart(v.node,v.offset),C.removeAllRanges(),ye>Xe?(C.addRange(x),C.extend(h.node,h.offset)):(x.setEnd(h.node,h.offset),C.addRange(x))}}}}for(B=[],C=o;C=C.parentNode;)C.nodeType===1&&B.push({element:C,left:C.scrollLeft,top:C.scrollTop});for(typeof o.focus=="function"&&o.focus(),o=0;ol?32:l,A.T=null,l=fc,fc=null;var s=$l,u=zl;if(ct=0,nn=$l=null,zl=0,(Be&6)!==0)throw Error(r(331));var o=Be;if(Be|=4,Qd(s.current),Gd(s,s.current,u,l),Be=o,$n(0,!1),he&&typeof he.onPostCommitFiberRoot=="function")try{he.onPostCommitFiberRoot(W,s)}catch{}return!0}finally{Y.p=i,A.T=a,uf(e,t)}}function of(e,t,l){t=kt(l,t),t=Zu(e.stateNode,t,2),e=Ql(e,t,2),e!==null&&(pn(e,2),dl(e))}function Ye(e,t,l){if(e.tag===3)of(e,e,l);else for(;t!==null;){if(t.tag===3){of(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Jl===null||!Jl.has(a))){e=kt(l,e),l=od(2),a=Ql(t,l,2),a!==null&&(rd(l,a,t,e),pn(a,2),dl(a));break}}t=t.return}}function vc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Yh;var i=new Set;a.set(t,i)}else i=a.get(t),i===void 0&&(i=new Set,a.set(t,i));i.has(l)||(cc=!0,i.add(l),e=Zh.bind(null,e,t,l),t.then(e,e))}function Zh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Ke===e&&(_e&l)===l&&(Fe===4||Fe===3&&(_e&62914560)===_e&&300>Pe()-Fi?(Be&2)===0&&sn(e,0):oc|=l,an===_e&&(an=0)),dl(e)}function rf(e,t){t===0&&(t=lo()),e=da(e,t),e!==null&&(pn(e,t),dl(e))}function kh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),rf(e,l)}function Vh(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,i=e.memoizedState;i!==null&&(l=i.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),rf(e,l)}function Jh(e,t){return Ue(e,t)}var ns=null,cn=null,yc=!1,is=!1,bc=!1,Fl=0;function dl(e){e!==cn&&e.next===null&&(cn===null?ns=cn=e:cn=cn.next=e),is=!0,yc||(yc=!0,Wh())}function $n(e,t){if(!bc&&is){bc=!0;do for(var l=!1,a=ns;a!==null;){if(e!==0){var i=a.pendingLanes;if(i===0)var s=0;else{var u=a.suspendedLanes,o=a.pingedLanes;s=(1<<31-Ze(42|e)+1)-1,s&=i&~(u&~o),s=s&201326741?s&201326741|1:s?s|2:0}s!==0&&(l=!0,hf(a,s))}else s=_e,s=oi(a,a===Ke?s:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(s&3)===0||hn(a,s)||(l=!0,hf(a,s));a=a.next}while(l);bc=!1}}function $h(){df()}function df(){is=yc=!1;var e=0;Fl!==0&&s0()&&(e=Fl);for(var t=Pe(),l=null,a=ns;a!==null;){var i=a.next,s=ff(a,t);s===0?(a.next=null,l===null?ns=i:l.next=i,i===null&&(cn=l)):(l=a,(e!==0||(s&3)!==0)&&(is=!0)),a=i}ct!==0&&ct!==5||$n(e),Fl!==0&&(Fl=0)}function ff(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,i=e.expirationTimes,s=e.pendingLanes&-62914561;0o)break;var U=d.transferSize,B=d.initiatorType;U&&Sf(B)&&(d=d.responseEnd,u+=U*(d"u"?null:document;function Rf(e,t,l){var a=on;if(a&&typeof t=="string"&&t){var i=Kt(t);i='link[rel="'+e+'"][href="'+i+'"]',typeof l=="string"&&(i+='[crossorigin="'+l+'"]'),Uf.has(i)||(Uf.add(i),e={rel:e,crossOrigin:l,href:t},a.querySelector(i)===null&&(t=a.createElement("link"),gt(t,"link",e),dt(t),a.head.appendChild(t)))}}function p0(e){Ol.D(e),Rf("dns-prefetch",e,null)}function v0(e,t){Ol.C(e,t),Rf("preconnect",e,t)}function y0(e,t,l){Ol.L(e,t,l);var a=on;if(a&&e&&t){var i='link[rel="preload"][as="'+Kt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(i+='[imagesrcset="'+Kt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(i+='[imagesizes="'+Kt(l.imageSizes)+'"]')):i+='[href="'+Kt(e)+'"]';var s=i;switch(t){case"style":s=rn(e);break;case"script":s=dn(e)}It.has(s)||(e=_({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),It.set(s,e),a.querySelector(i)!==null||t==="style"&&a.querySelector(Pn(s))||t==="script"&&a.querySelector(ei(s))||(t=a.createElement("link"),gt(t,"link",e),dt(t),a.head.appendChild(t)))}}function b0(e,t){Ol.m(e,t);var l=on;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",i='link[rel="modulepreload"][as="'+Kt(a)+'"][href="'+Kt(e)+'"]',s=i;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":s=dn(e)}if(!It.has(s)&&(e=_({rel:"modulepreload",href:e},t),It.set(s,e),l.querySelector(i)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(ei(s)))return}a=l.createElement("link"),gt(a,"link",e),dt(a),l.head.appendChild(a)}}}function g0(e,t,l){Ol.S(e,t,l);var a=on;if(a&&e){var i=_a(a).hoistableStyles,s=rn(e);t=t||"default";var u=i.get(s);if(!u){var o={loading:0,preload:null};if(u=a.querySelector(Pn(s)))o.loading=5;else{e=_({rel:"stylesheet",href:e,"data-precedence":t},l),(l=It.get(s))&&Rc(e,l);var d=u=a.createElement("link");dt(d),gt(d,"link",e),d._p=new Promise(function(j,U){d.onload=j,d.onerror=U}),d.addEventListener("load",function(){o.loading|=1}),d.addEventListener("error",function(){o.loading|=2}),o.loading|=4,rs(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:o},i.set(s,u)}}}function x0(e,t){Ol.X(e,t);var l=on;if(l&&e){var a=_a(l).hoistableScripts,i=dn(e),s=a.get(i);s||(s=l.querySelector(ei(i)),s||(e=_({src:e,async:!0},t),(t=It.get(i))&&Hc(e,t),s=l.createElement("script"),dt(s),gt(s,"link",e),l.head.appendChild(s)),s={type:"script",instance:s,count:1,state:null},a.set(i,s))}}function j0(e,t){Ol.M(e,t);var l=on;if(l&&e){var a=_a(l).hoistableScripts,i=dn(e),s=a.get(i);s||(s=l.querySelector(ei(i)),s||(e=_({src:e,async:!0,type:"module"},t),(t=It.get(i))&&Hc(e,t),s=l.createElement("script"),dt(s),gt(s,"link",e),l.head.appendChild(s)),s={type:"script",instance:s,count:1,state:null},a.set(i,s))}}function Hf(e,t,l,a){var i=(i=xe.current)?os(i):null;if(!i)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=rn(l.href),l=_a(i).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=rn(l.href);var s=_a(i).hoistableStyles,u=s.get(e);if(u||(i=i.ownerDocument||i,u={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},s.set(e,u),(s=i.querySelector(Pn(e)))&&!s._p&&(u.instance=s,u.state.loading=5),It.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},It.set(e,l),s||S0(i,e,l,u.state))),t&&a===null)throw Error(r(528,""));return u}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=dn(l),l=_a(i).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function rn(e){return'href="'+Kt(e)+'"'}function Pn(e){return'link[rel="stylesheet"]['+e+"]"}function wf(e){return _({},e,{"data-precedence":e.precedence,precedence:null})}function S0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),gt(t,"link",l),dt(t),e.head.appendChild(t))}function dn(e){return'[src="'+Kt(e)+'"]'}function ei(e){return"script[async]"+e}function Bf(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Kt(l.href)+'"]');if(a)return t.instance=a,dt(a),a;var i=_({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),dt(a),gt(a,"style",i),rs(a,l.precedence,e),t.instance=a;case"stylesheet":i=rn(l.href);var s=e.querySelector(Pn(i));if(s)return t.state.loading|=4,t.instance=s,dt(s),s;a=wf(l),(i=It.get(i))&&Rc(a,i),s=(e.ownerDocument||e).createElement("link"),dt(s);var u=s;return u._p=new Promise(function(o,d){u.onload=o,u.onerror=d}),gt(s,"link",a),t.state.loading|=4,rs(s,l.precedence,e),t.instance=s;case"script":return s=dn(l.src),(i=e.querySelector(ei(s)))?(t.instance=i,dt(i),i):(a=l,(i=It.get(s))&&(a=_({},l),Hc(a,i)),e=e.ownerDocument||e,i=e.createElement("script"),dt(i),gt(i,"link",a),e.head.appendChild(i),t.instance=i);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,rs(a,l.precedence,e));return t.instance}function rs(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),i=a.length?a[a.length-1]:null,s=i,u=0;u title"):null)}function N0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Yf(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function A0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var i=rn(a.href),s=t.querySelector(Pn(i));if(s){t=s._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=fs.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=s,dt(s);return}s=t.ownerDocument||t,a=wf(a),(i=It.get(i))&&Rc(a,i),s=s.createElement("link"),dt(s);var u=s;u._p=new Promise(function(o,d){u.onload=o,u.onerror=d}),gt(s,"link",a),l.instance=s}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=fs.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var wc=0;function C0(e,t){return e.stylesheets&&e.count===0&&hs(e,e.stylesheets),0wc?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(i)}}:null}function fs(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)hs(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var ms=null;function hs(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ms=new Map,t.forEach(T0,e),ms=null,fs.call(e))}function T0(e,t){if(!(t.state.loading&4)){var l=ms.get(e);if(l)var a=l.get(null);else{l=new Map,ms.set(e,l);for(var i=e.querySelectorAll("link[data-precedence],style[data-precedence]"),s=0;s"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(m){console.error(m)}}return c(),Zc.exports=K0(),Zc.exports}var k0=Z0();function be(c){return Array.isArray(c)?c:[]}function hm(c){const m=new Set;return c.map(y=>y.trim()).filter(y=>{const r=y.toLowerCase();return!y||m.has(r)?!1:(m.add(r),!0)})}function il(c){const m=Ns.some(y=>y.value===c.streamMode)?c.streamMode:"auto";return{...c,streamMode:m,models:be(c.models),allowedGroupIds:be(c.allowedGroupIds),openaiAccounts:be(c.openaiAccounts),kiroAccounts:be(c.kiroAccounts)}}function ui(c){return{...c,aliases:be(c.aliases)}}function V0(c){return{...c,apiKeys:be(c.apiKeys),logs:be(c.logs)}}class Cs extends Error{status;payload;constructor(m,y,r){super(y),this.status=m,this.payload=r}}const J0={home:"M3 10.5 12 3l9 7.5V21a1 1 0 0 1-1 1h-5v-7H9v7H4a1 1 0 0 1-1-1z",users:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",key:"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78ZM14 8l7-7M21 8h-5V3",models:"M12 2 4 6v12l8 4 8-4V6zM4 6l8 4 8-4M12 10v12",image:"M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2ZM8.5 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM21 16l-5-5L5 21",route:"M4 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM20 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM7 16h3a4 4 0 0 0 4-4V8h3",logs:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M8 13h8M8 17h6",settings:"M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 8.92 4a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.31.39.57.71.71.23.1.49.18.8.2H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z",search:"M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z",copy:"M8 8h11a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM4 16H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v1",ban:"M4.93 4.93 19.07 19.07M22 12A10 10 0 1 1 2 12a10 10 0 0 1 20 0Z",check:"M20 6 9 17l-5-5",moon:"M21 12.8A8.5 8.5 0 1 1 11.2 3 6.5 6.5 0 0 0 21 12.8Z",sun:"M12 4V2M12 22v-2M4.93 4.93 3.52 3.52M20.48 20.48l-1.41-1.41M4 12H2M22 12h-2M4.93 19.07l-1.41 1.41M20.48 3.52l-1.41 1.41M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z",plus:"M12 5v14M5 12h14"};function Ot({name:c}){return n.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",className:"icon",children:n.jsx("path",{d:J0[c]})})}async function pe(c,m){const y=new Headers(m?.headers);y.set("Content-Type","application/json");const r=window.sessionStorage.getItem("capi-admin-token");r&&y.set("Authorization",`Bearer ${r}`);const E=await fetch(c,{credentials:"include",...m,headers:y});if(!E.ok){const O=await E.json().catch(()=>null);throw new Cs(E.status,O?.error?.message||`Request failed: ${E.status}`,O)}return E.json()}async function $0(c,m){const y=new Headers,r=window.sessionStorage.getItem("capi-admin-token");r&&y.set("Authorization",`Bearer ${r}`);const E=await fetch(c,{credentials:"include",method:"POST",headers:y,body:m});if(!E.ok){const O=await E.json().catch(()=>null);throw new Cs(E.status,O?.error?.message||`Request failed: ${E.status}`,O)}return E.json()}const rm=[{id:"overview",label:"概览",icon:"home"},{id:"users",label:"用户",icon:"users"},{id:"groups",label:"分组",icon:"users"},{id:"keys",label:"密钥",icon:"key"},{id:"models",label:"模型",icon:"models"},{id:"drawing",label:"绘图",icon:"image"},{id:"channels",label:"渠道",icon:"route"},{id:"logs",label:"日志",icon:"logs"},{id:"settings",label:"设置",icon:"settings"}],eo=[{value:"kiro",label:"Kiro / Amazon Q"},{value:"codex",label:"Codex / ChatGPT OAuth"},{value:"cpa",label:"CPA / CLIProxyAPI"},{value:"openai",label:"OpenAI"},{value:"anthropic",label:"Anthropic / Claude"},{value:"google",label:"Google Gemini"},{value:"deepseek",label:"DeepSeek"},{value:"openrouter",label:"OpenRouter"},{value:"groq",label:"Groq"},{value:"siliconflow",label:"SiliconFlow"},{value:"moonshot",label:"Moonshot"},{value:"compatible",label:"OpenAI 兼容接口"}],pm="https://api.openai.com/v1",Ts="https://chatgpt.com/backend-api",vm="http://localhost:8317/v1",ym="https://codewhisperer.us-east-1.amazonaws.com",bm="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2, gpt-image-1",W0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2",F0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, claude-sonnet-4, gemini-3.1-pro",I0="claude-sonnet-4.5, claude-sonnet-4, claude-haiku-4.5, claude-opus-4.5",Fc=[{provider:"kiro",label:"Kiro / Amazon Q",name:"Kiro 账号池",baseUrl:ym,models:I0.split(",").map(c=>c.trim())},{provider:"openai",label:"OpenAI",name:"OpenAI 主线路",baseUrl:pm,models:W0.split(",").map(c=>c.trim())},{provider:"codex",label:"Codex 账号池",name:"Codex 账号池",baseUrl:Ts,models:bm.split(",").map(c=>c.trim())},{provider:"cpa",label:"CPA / CLIProxyAPI",name:"CPA 本地代理",baseUrl:vm,models:F0.split(",").map(c=>c.trim())},{provider:"compatible",label:"OpenAI 兼容接口",name:"兼容渠道",baseUrl:"",models:[]},{provider:"openrouter",label:"OpenRouter",name:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",models:[]},{provider:"google",label:"Google Gemini",name:"Gemini",baseUrl:"",models:[]},{provider:"anthropic",label:"Anthropic / Claude",name:"Claude",baseUrl:"",models:[]}];function Aa(c){return Fc.find(m=>m.provider===c)||Fc[2]}function gm(c){const m=Aa(c);return{name:m.name,provider:m.provider,baseUrl:m.baseUrl,models:[...m.models],streamMode:"auto"}}function P0(c){const m=c?.trim().toLowerCase();return m&&({free:"Free",plus:"Plus",pro:"Pro",team:"Team",enterprise:"Enterprise"}[m]||c)||"套餐未知"}function dm(c){return c?{upstream_token_invalidated:"Token 已失效",upstream_invalid_api_key:"API Key 无效",upstream_account_error:"账号错误",upstream_accounts_unavailable:"账号池不可用",upstream_error:"上游错误"}[c]||c:""}function Es(c){return c==="openai"?pm:c==="codex"?Ts:c==="cpa"||c==="cliproxyapi"?vm:c==="kiro"?ym:""}function Ic(c){return hm(c.split(/[\s,;,;]+/))}function ep(c){return hm(c.split(/[\n,;,;]+/).map(m=>m.trim()))}function xm(c){const m=ep(c);return m.length===0?{}:m.length===1?{upstreamApiKey:m[0]}:{upstreamApiKeys:m}}const Ns=[{value:"auto",label:"自动",description:"按请求参数处理"},{value:"real",label:"真流",description:"直连上游 SSE"},{value:"fake",label:"假流",description:"非流转 SSE"},{value:"disabled",label:"禁用流",description:"流式请求跳过"}];function el(c){if(!c)return"未使用";const m=new Date(c);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(m)}function fm(c){if(!c)return"";const m=new Date(c);if(Number.isNaN(m.getTime()))return"";const y=m.getTimezoneOffset()*6e4;return new Date(m.getTime()-y).toISOString().slice(0,16)}function tp(c){if(!c)return"";const m=new Date(c);return Number.isNaN(m.getTime())?"":m.toISOString()}function lp(c){if(!c)return"-";const m=new Date(c);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).format(m)}function _t(c){return{active:"正常",disabled:"禁用",limited:"受限",overdue:"欠费",healthy:"正常",standby:"备用",available:"Available",success:"成功",failed:"失败"}[c]||c}function ci(c,m=2){const y=Number(c||0);return new Intl.NumberFormat("zh-CN",{minimumFractionDigits:m,maximumFractionDigits:m}).format(y)}function Ca(c){return new Intl.NumberFormat("zh-CN").format(Math.max(0,Math.round(Number(c||0))))}function to(c){return c.model?c.model:c.errorCode==="invalid_api_key"?"密钥无效":c.errorCode==="model_not_available"?"模型不可用":c.errorCode==="insufficient_quota"?"额度不足":c.errorCode==="rate_limit_exceeded"?"请求过快":c.errorCode||"请求失败"}function ap(c){return c.model||(c.errorCode?`错误:${c.errorCode}`:"-")}function np(c){return c.channel||(c.apiKeyPrefix?`Key ${c.apiKeyPrefix}`:"-")}function ip(c){const m=be(c);if(m.length===0)return"未绑定模型";const y=m.slice(0,2).join(", ");return m.length>2?`${y} · 其余 ${m.length-2} 个`:y}function sl(c){return c==="cliproxyapi"||c==="cli-proxy-api"?"CPA / CLIProxyAPI":eo.find(m=>m.value===c)?.label||c||"Custom"}function $c(c){const m=`${c.vendor} ${c.id} ${c.name}`.toLowerCase();return m.includes("cliproxyapi")||/\bcpa\b/.test(m)?"cpa":m.includes("openai")||/\bgpt[-_/]/.test(m)||m.includes("o1-")||m.includes("o3-")?"openai":m.includes("anthropic")||m.includes("claude")?"anthropic":m.includes("google")||m.includes("gemini")||m.includes("gcli-")?"google":m.includes("deepseek")?"deepseek":m.includes("openrouter")?"openrouter":m.includes("groq")?"groq":m.includes("siliconflow")?"siliconflow":m.includes("moonshot")||m.includes("kimi")?"moonshot":c.vendor&&c.vendor.toLowerCase()!=="custom"?c.vendor.toLowerCase():"compatible"}function mm({provider:c}){if(c==="deepseek")return n.jsx("span",{className:"provider-icon provider-icon-deepseek","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("path",{transform:"translate(2.4 4.4)",d:"M26.517 3.395c-.282-.138-.403.125-.568.258-.057.044-.105.1-.152.152-.413.44-.895.73-1.524.695-.92-.052-1.705.237-2.4.941-.147-.868-.638-1.386-1.384-1.718-.39-.173-.786-.346-1.06-.721-.19-.268-.243-.566-.338-.86-.061-.176-.121-.357-.325-.388-.222-.034-.309.151-.396.307-.347.635-.481 1.334-.468 2.042.03 1.594.703 2.863 2.04 3.765.152.104.191.207.143.359-.091.31-.2.613-.295.924-.06.198-.151.242-.364.155-.734-.306-1.367-.76-1.927-1.308-.951-.92-1.81-1.934-2.882-2.729-.252-.185-.504-.358-.764-.522-1.094-1.062.143-1.935.43-2.038.3-.108.104-.48-.864-.475-.968.004-1.853.328-2.982.76-.165.065-.339.112-.516.151-1.024-.194-2.088-.237-3.199-.112-2.092.233-3.763 1.222-4.991 2.91C.254 7.972-.093 10.278.332 12.682c.446 2.535 1.74 4.633 3.728 6.274 2.062 1.7 4.436 2.534 7.145 2.375 1.645-.095 3.476-.316 5.542-2.064.521.259 1.068.363 1.975.44.699.065 1.371-.034 1.892-.142.816-.173.76-.929.465-1.067-2.392-1.114-1.866-.661-2.344-1.027 1.215-1.438 3.071-3.993 3.644-7.473.056-.384.128-.925.12-1.236-.005-.19.038-.263.255-.285.6-.069 1.18-.233 1.715-.527 1.55-.846 2.175-2.237 2.322-3.903.022-.255-.005-.518-.274-.652ZM13.014 18.395c-2.318-1.823-3.442-2.423-3.906-2.397-.434.026-.356.523-.26.847.1.32.23.54.412.82.126.186.213.462-.126.67-.746.461-2.044-.156-2.105-.186-1.51-.89-2.773-2.064-3.664-3.67-.86-1.545-1.358-3.204-1.44-4.974-.022-.427.104-.578.529-.656.56-.103 1.137-.125 1.697-.043 2.366.346 4.379 1.403 6.068 3.079.963.954 1.692 2.094 2.443 3.208.799 1.183 1.658 2.31 2.752 3.234.387.324.695.57.99.751-.89.1-2.374.121-3.39-.683Zm1.111-7.146c0-.19.152-.341.343-.341.043 0 .082.009.117.021.048.018.092.044.126.083.061.06.096.146.096.237a.341.341 0 0 1-.343.341.34.34 0 0 1-.339-.341Zm3.451 1.77c-.222.09-.443.168-.656.177-.33.017-.69-.117-.885-.281-.304-.255-.521-.397-.612-.842-.039-.19-.017-.483.017-.652.078-.362-.009-.595-.265-.807-.208-.172-.473-.22-.764-.22-.108 0-.208-.048-.282-.086-.121-.061-.221-.212-.126-.398.031-.06.178-.207.213-.233.395-.225.85-.151 1.272.018.39.16.686.453 1.111.867.434.501.512.639.759 1.015.196.294.373.596.495.942.073.215-.022.392-.277.5Z"})]})});if(c==="openai")return n.jsx("span",{className:"provider-icon provider-icon-openai","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("g",{transform:"translate(7 7.5) scale(0.065)",fill:"currentColor",stroke:"none",children:n.jsx("path",{d:"M267.06 111.34a71.78 71.78 0 0 0-6.17-58.91c-14.5-25.15-43.55-38.09-71.9-32.03A71.78 71.78 0 0 0 135.1.5C106 .43 80.21 19.16 71.29 46.85a71.79 71.79 0 0 0-47.98 34.8c-14.6 25.1-11.28 56.75 8.22 78.3a71.78 71.78 0 0 0 6.16 58.9c14.5 25.16 43.56 38.1 71.91 32.04a71.76 71.76 0 0 0 53.89 24.02c29.12.02 54.92-18.72 63.84-46.44a71.79 71.79 0 0 0 47.98-34.8c14.58-25.1 11.25-56.72-8.24-78.27zm-107.9 150.77a53.15 53.15 0 0 1-34.15-12.35c.43-.24 1.2-.66 1.7-.96l56.68-32.73a9.22 9.22 0 0 0 4.66-8.06v-79.9l23.95 13.83a.85.85 0 0 1 .47.66v66.16a53.42 53.42 0 0 1-53.3 53.35zM44.6 213.16a53.13 53.13 0 0 1-6.36-35.75c.42.25 1.15.7 1.68 1l56.68 32.73a9.24 9.24 0 0 0 9.31 0l69.2-39.95v27.66a.87.87 0 0 1-.34.74l-57.29 33.07a53.42 53.42 0 0 1-72.88-19.5zM29.7 90.05a53.1 53.1 0 0 1 27.76-23.36c0 .49-.03 1.36-.03 1.96v65.46a9.22 9.22 0 0 0 4.65 8.05l69.2 39.95-23.95 13.83a.86.86 0 0 1-.81.07L49.2 162.9A53.42 53.42 0 0 1 29.7 90.05zm196.8 45.8L157.3 95.9l23.95-13.82a.86.86 0 0 1 .81-.07l57.3 33.08a53.37 53.37 0 0 1-8.24 96.29v-65.46a9.2 9.2 0 0 0-4.62-8.06zm23.84-35.89c-.42-.26-1.15-.7-1.68-1.01l-56.68-32.73a9.25 9.25 0 0 0-9.31 0l-69.2 39.95V78.5a.87.87 0 0 1 .35-.74l57.28-33.05a53.35 53.35 0 0 1 79.24 55.25zM100.11 149.24l-23.96-13.83a.85.85 0 0 1-.46-.66V68.6a53.37 53.37 0 0 1 87.52-40.95c-.42.24-1.19.66-1.7.96l-56.68 32.73a9.22 9.22 0 0 0-4.66 8.06l-.04 79.85zm13.01-28.05L144 103.3l30.88 17.83v35.68L144 174.63l-30.88-17.82v-35.62z"})})]})});const m=c==="codex"?"C":c==="cpa"||c==="cliproxyapi"?"CPA":c==="anthropic"?"A":c==="google"?"✦":c==="openrouter"?"↗":c==="groq"?"G":c==="siliconflow"?"S":c==="moonshot"?"M":"◇";return n.jsx("span",{className:`provider-icon provider-icon-${c}`,"aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("text",{x:"16",y:"21",textAnchor:"middle",children:m})]})})}async function As(c){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(c);return}const m=document.createElement("textarea");m.value=c,m.setAttribute("readonly","true"),m.style.position="fixed",m.style.opacity="0",document.body.appendChild(m),m.select(),document.execCommand("copy"),document.body.removeChild(m)}function _l(){return window.location.origin}function sp(){return`${_l()}/api/auth/discord/callback`}function up(){return`${_l()}/`}function Wc(c){return{...c,redirectUri:c.redirectUri&&!c.redirectUri.includes("localhost")?c.redirectUri:sp(),authSuccessUrl:c.authSuccessUrl&&!c.authSuccessUrl.includes("localhost")?c.authSuccessUrl:up(),blockedGuildIds:be(c.blockedGuildIds),sessionTtlHours:c.sessionTtlHours||168}}function Ms(c){return c==="email"||c==="discord"?c:"username"}function cp(c){const y=(c.split("@")[0]||"user").toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^[-_]+|[-_]+$/g,"");return(y.length>=3?y:"user").slice(0,24)}function op(){const[c,m]=g.useState("home"),[y,r]=g.useState("login"),[E,O]=g.useState(null),[K,P]=g.useState("overview"),[T,b]=g.useState(()=>{const H=window.localStorage.getItem("capi-theme");return H==="light"||H==="dark"?H:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}),[G,_]=g.useState("comfortable"),[ae,te]=g.useState(null),[de,le]=g.useState([]),[ne,ie]=g.useState([]),[ge,me]=g.useState([]),[Ce,F]=g.useState([]),[ve,D]=g.useState([]),[ee,oe]=g.useState(""),[Ne,Me]=g.useState(""),[ue,Q]=g.useState(null),[re,V]=g.useState(""),[A,Y]=g.useState(""),[p,z]=g.useState(!1),$=g.useMemo(()=>{const H=ee.trim().toLowerCase();return H?de.filter(X=>`${X.id} ${X.name} ${X.email}`.toLowerCase().includes(H)):de},[ee,de]);async function f(){const H=new Date().getTimezoneOffset(),[X,I,W,he,qe,Ze]=await Promise.all([pe(`/api/overview?timezoneOffset=${H}`),pe("/api/users"),pe("/api/channels"),pe("/api/models"),pe("/api/logs"),pe("/api/groups")]),Rt=be(I.users),Dl=be(W.channels).map(il),sa=be(he.models).map(ui),Ta=be(qe.logs),Ea=be(Ze.groups);te(X),le(Rt),ie(Dl),me(Ea),F(sa),D(Ta),Me(Ul=>Ul&&Rt.some(fl=>fl.id===Ul)?Ul:Rt[0]?.id||""),Rt.length===0&&Q(null),z(!0)}async function N(H){const X=await pe(`/api/users/${H}`);Q(V0(X))}async function q(H,X){const I=await pe(`/api/users/${H}`,{method:"PATCH",body:JSON.stringify(X)});le(W=>W.map(he=>he.id===H?I.user:he)),Q(W=>W?.user.id===H?{...W,user:I.user}:W),V("已更新用户"),window.setTimeout(()=>V(""),1800)}async function L(H,X,I={}){const W=await pe("/api/users/bulk",{method:"POST",body:JSON.stringify({userIds:H,action:X,...I})}),he=new Map(be(W.users).map(qe=>[qe.id,qe]));le(qe=>qe.map(Ze=>he.get(Ze.id)||Ze)),Q(qe=>{if(!qe)return qe;const Ze=he.get(qe.user.id);return Ze?{...qe,user:Ze}:qe}),V(`已处理 ${W.updated} 个用户`),window.setTimeout(()=>V(""),1800)}async function Z(H){const X=await pe(`/api/users/${H}/api-keys`,{method:"POST",body:JSON.stringify({name:"Console Key"})});ue?.user.id===H&&Q({...ue,apiKeys:[...ue.apiKeys,X.apiKey]}),Y(X.secret),await As(X.secret),V("新 Key 已创建并复制,请立即保存"),window.setTimeout(()=>V(""),2400)}async function xe(H){window.confirm("删除这个 Key?删除后使用它的请求会立即失效。")&&(await pe(`/api/api-keys/${H}`,{method:"DELETE"}),Q(X=>X&&{...X,apiKeys:X.apiKeys.filter(I=>I.id!==H)}),V("Key 已删除"),window.setTimeout(()=>V(""),1800))}async function M(H,X){const I=await pe(`/api/api-keys/${H}`,{method:"PATCH",body:JSON.stringify(X)});Q(W=>W&&{...W,apiKeys:W.apiKeys.map(he=>he.id===H?I.apiKey:he)}),V("Key 已更新"),window.setTimeout(()=>V(""),1800)}async function je(H,X){const I=await pe(`/api/channels/${H}`,{method:"PATCH",body:JSON.stringify(X)});ie(W=>W.map(he=>he.id===H?il(I.channel):he)),Ie(I.removedModels),V("渠道已更新"),window.setTimeout(()=>V(""),1800)}async function Se(H){const X=ne.find(W=>W.id===H);if(!window.confirm(`删除渠道「${X?.name||H}」?`))return;const I=await pe(`/api/channels/${H}`,{method:"DELETE"});ie(W=>W.filter(he=>he.id!==H)),Ie(I.removedModels),V("渠道已删除"),window.setTimeout(()=>V(""),1800)}async function ot(H){const X=await pe("/api/groups",{method:"POST",body:JSON.stringify(H)});me(I=>[...I,X.group]),V("分组已创建"),window.setTimeout(()=>V(""),1800)}async function J(H,X){const I=await pe(`/api/groups/${H}`,{method:"PATCH",body:JSON.stringify(X)});me(W=>W.map(he=>he.id===H?I.group:he)),V("分组已更新"),window.setTimeout(()=>V(""),1800)}async function Je(H){const X=ge.find(I=>I.id===H);window.confirm(`删除分组「${X?.name||H}」?删除后渠道的可见范围会移除该分组。`)&&(await pe(`/api/groups/${H}`,{method:"DELETE"}),me(I=>I.filter(W=>W.id!==H)),ie(I=>I.map(W=>({...W,allowedGroupIds:W.allowedGroupIds.filter(he=>he!==H)}))),V("分组已删除"),window.setTimeout(()=>V(""),1800))}async function ut(H,X){const I=be(X).map(Rt=>Rt.trim()).filter(Boolean),W=await pe(`/api/channels/${H}/sync-models`,{method:"POST",body:JSON.stringify(I.length?{models:I}:{})}),he=il(W.channel),qe=be(W.addedModels).map(ui),Ze=be(W.models);ie(Rt=>Rt.map(Dl=>Dl.id===H?he:Dl)),qe.length>0&&F(Rt=>{const Dl=new Set(Rt.map(sa=>sa.id.toLowerCase()));return[...Rt,...qe.filter(sa=>!Dl.has(sa.id.toLowerCase()))]}),Ie(W.removedModels),V(I.length?`已保存 ${Ze.length} 个模型`:Ze.length?`已拉取 ${Ze.length} 个模型`:"上游没有返回模型"),window.setTimeout(()=>V(""),2200)}function Ie(H){const X=new Set(be(H).map(I=>I.toLowerCase()));X.size!==0&&(F(I=>I.filter(W=>!X.has(W.id.toLowerCase()))),Q(I=>I&&{...I,apiKeys:I.apiKeys.map(W=>({...W,allowedModels:W.allowedModels.filter(he=>!X.has(he.toLowerCase()))}))}))}async function tl(H){try{const X=await pe(`/api/channels/${H}/check`,{method:"POST",body:JSON.stringify({})});ie(I=>I.map(W=>W.id===H?il(X.channel):W)),V(X.ok?`渠道可用,检测到 ${be(X.models).length} 个模型`:"渠道检测失败")}catch(X){const I=X instanceof Cs?X.payload?.channel:null;I&&ie(W=>W.map(he=>he.id===H?il(I):he)),V(X instanceof Error?X.message:"渠道检测失败")}window.setTimeout(()=>V(""),2400)}async function k(H=gm("codex")){const X=await pe("/api/channels",{method:"POST",body:JSON.stringify(H)});ie(I=>[...I,il(X.channel)]),V("渠道已创建,可继续拉取模型或检测渠道"),window.setTimeout(()=>V(""),2400)}async function mt(H,X){const I=new FormData;I.append("file",X);const W=await $0(`/api/channels/${encodeURIComponent(H)}/import-openai-accounts`,I);ie(he=>he.map(qe=>qe.id===W.channel.id?il(W.channel):qe)),V(`新增 ${W.created??W.imported} 个账号${W.updated?`,更新 ${W.updated} 个已有账号`:""}${W.skipped?`,跳过 ${W.skipped} 个`:""}`),window.setTimeout(()=>V(""),2600)}async function Ut(H,X=!1,I=""){const W=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/check`,{method:"POST",body:JSON.stringify({onlyInvalid:X,accountId:I})});ie(he=>he.map(qe=>qe.id===W.channel.id?il(W.channel):qe)),V(`${X?"无效账号复检":"账号测活"}完成:${W.healthy}/${W.checked} 可用${W.failed?`,无效 ${W.failed}`:""}`),window.setTimeout(()=>V(""),3e3)}async function R(H){const X=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/deduplicate`,{method:"POST",body:JSON.stringify({})});ie(I=>I.map(W=>W.id===X.channel.id?il(X.channel):W)),V(X.removed?`已合并 ${X.removed} 个重复账号`:"未发现可识别的重复账号"),window.setTimeout(()=>V(""),2600)}async function Ue(H,X){const I=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/${encodeURIComponent(X)}`,{method:"DELETE"});ie(W=>W.map(he=>he.id===I.channel.id?il(I.channel):he)),V("账号已删除"),window.setTimeout(()=>V(""),1800)}async function rt(H){return pe(`/api/channels/${encodeURIComponent(H)}/openai-oauth/start`,{method:"POST",body:JSON.stringify({})})}async function jt(H,X){const I=await pe(`/api/channels/${encodeURIComponent(H)}/openai-oauth/complete`,{method:"POST",body:JSON.stringify(X)});return ie(W=>W.map(he=>he.id===I.channel.id?il(I.channel):he)),V("已通过 OAuth 添加账号"),window.setTimeout(()=>V(""),2400),I}async function ht(H){const X=await pe("/api/models",{method:"POST",body:JSON.stringify(H)});F(I=>[...I,ui(X.model)]),V("模型已添加"),window.setTimeout(()=>V(""),1800)}async function Pe(H,X){const I=await pe(`/api/models/${encodeURIComponent(H)}`,{method:"PATCH",body:JSON.stringify(X)});F(W=>W.map(he=>he.id===H?ui(I.model):he)),V("模型已更新"),window.setTimeout(()=>V(""),1600)}async function zs(H){window.confirm(`删除模型 ${H}?渠道和 Key 中的引用也会一起清理。`)&&(await pe(`/api/models/${encodeURIComponent(H)}`,{method:"DELETE"}),F(X=>X.filter(I=>I.id!==H)),ie(X=>X.map(I=>({...I,models:I.models.filter(W=>W!==H)}))),Q(X=>X&&{...X,apiKeys:X.apiKeys.map(I=>({...I,allowedModels:I.allowedModels.filter(W=>W!==H)}))}),V("模型已删除"),window.setTimeout(()=>V(""),1800))}async function mn(H,X="已复制"){await As(H),V(X),window.setTimeout(()=>V(""),1600)}function na(H,X){if(H instanceof Cs&&H.status===401){z(!1),r("login"),m("auth");return}V(X)}async function ia(){try{const H=await pe("/api/auth/status");if(O(H),!H.initialized){r("setup"),m("auth");return}if(!H.authenticated){r("login"),m("auth");return}m(H.session?.role==="admin"?"console":"account")}catch(H){na(H,"认证状态加载失败")}}async function Os(){await pe("/api/auth/logout",{method:"POST"}),window.sessionStorage.removeItem("capi-admin-token"),O(null),m("home")}return g.useEffect(()=>{let H=!1;return pe("/api/auth/status").then(X=>{H||(O(X),X.authenticated&&X.session&&m(X.session.role==="admin"?"console":"account"))}).catch(()=>{}),()=>{H=!0}},[]),g.useEffect(()=>{c==="console"&&(z(!1),f().catch(H=>na(H,"加载数据失败")))},[c]),g.useEffect(()=>{c!=="console"||!p||N(Ne).catch(H=>na(H,"加载用户详情失败"))},[Ne,c,p]),g.useEffect(()=>{window.localStorage.setItem("capi-theme",T)},[T]),g.useEffect(()=>{window.scrollTo({top:0,left:0})},[c,K]),c==="home"?n.jsx(fp,{theme:T,setTheme:b,enterConsole:ia}):c==="auth"?n.jsx(rp,{theme:T,mode:y,status:E,setTheme:b,setMode:r,goHome:()=>m("home"),onAuthenticated:H=>{O(X=>X?{...X,authenticated:!0,initialized:!0,session:H}:null),m(H.role==="admin"?"console":"account")}}):c==="account"?n.jsx(dp,{theme:T,setTheme:b,goHome:()=>m("home"),openLogin:ia}):n.jsxs("div",{className:"app-shell","data-theme":T,"data-density":G,children:[n.jsxs("aside",{className:"sidebar",children:[n.jsxs("div",{className:"ios-window-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsxs("div",{className:"brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"聚合网关"})]})]}),n.jsx("nav",{children:rm.map(H=>n.jsxs("button",{className:K===H.id?"nav-item active":"nav-item",onClick:()=>P(H.id),children:[n.jsx(Ot,{name:H.icon}),n.jsx("span",{className:"nav-label",children:H.label})]},H.id))}),n.jsxs("div",{className:"sidebar-footer",children:[n.jsx("span",{children:"Gateway"}),n.jsxs("strong",{children:[n.jsx("span",{className:"pulse-dot"}),"Online"]})]})]}),n.jsxs("main",{className:"content",children:[n.jsxs("header",{className:"topbar",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Admin Console"}),n.jsx("h1",{children:rm.find(H=>H.id===K)?.label})]}),n.jsxs("div",{className:"topbar-actions",children:[n.jsx(qp,{value:G,options:[{value:"comfortable",label:"舒适"},{value:"compact",label:"紧凑"}],onChange:H=>_(H)}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>b(T==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:T==="dark"?"sun":"moon"}),n.jsx("span",{children:T==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:()=>f().catch(H=>na(H,"刷新失败")),children:"刷新"}),n.jsx("button",{className:"secondary-button home-link",onClick:()=>m("home"),children:"首页"}),n.jsx("button",{className:"secondary-button",onClick:Os,children:"退出"})]})]}),K==="overview"&&n.jsx(mp,{overview:ae,channels:ne,logs:ve,onNavigate:H=>{P(H),H==="channels"&&ne.length===0&&V("渠道页可以创建第一个上游"),H==="logs"&&ve.length===0&&V("暂无异常日志"),window.setTimeout(()=>V(""),1800)}}),K==="users"&&n.jsx(pp,{users:$,query:ee,selectedUser:ue,onQuery:oe,onSelect:Me,onUpdate:q,onBulkUpdate:L,onCreateKey:Z,groups:ge,onOpenRegistration:()=>{P("settings"),V("在账号与注册里开放注册,用户即可自助创建账号"),window.setTimeout(()=>V(""),2400)}}),K==="groups"&&n.jsx(wp,{groups:ge,onCreate:ot,onUpdate:J,onDelete:Je}),K==="keys"&&n.jsx(vp,{selectedUser:ue,onCreateKey:Z,onUpdateKey:M,onDeleteKey:xe}),K==="models"&&n.jsx(bp,{models:Ce,onCopy:mn,onCreate:ht,onUpdate:Pe,onDelete:zs}),K==="drawing"&&n.jsx(jp,{channels:ne,onCreate:k,onImport:mt,onCheckAccounts:Ut,onDeduplicateAccounts:R,onDeleteAccount:Ue,onUpdate:je,onStartOAuth:rt,onCompleteOAuth:jt}),K==="channels"&&n.jsx(_p,{channels:ne,groups:ge,onUpdate:je,onCreate:k,onImport:mt,onDelete:Se,onSyncModels:ut,onCheck:tl}),K==="logs"&&n.jsx(Up,{logs:ve,onCopy:mn}),K==="settings"&&n.jsx(Hp,{models:Ce,channels:ne,groups:ge})]}),A&&n.jsx("div",{className:"secret-dialog-backdrop",role:"presentation",children:n.jsxs("section",{className:"secret-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"secret-dialog-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"One-time secret"}),n.jsx("h2",{id:"secret-dialog-title",children:"完整 API Key"})]}),n.jsx("p",{children:"完整密钥只显示这一次。列表中的星号内容只是识别前缀,不能用于 API 调用。"}),n.jsx("code",{children:A}),n.jsxs("div",{className:"secret-dialog-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>{As(A),V("完整 Key 已复制"),window.setTimeout(()=>V(""),1800)},children:"复制"}),n.jsx("button",{className:"primary-button",onClick:()=>Y(""),children:"完成"})]})]})}),re&&n.jsx("div",{className:"toast",children:re})]})}function rp({theme:c,mode:m,status:y,setTheme:r,setMode:E,goHome:O,onAuthenticated:K}){const[P,T]=g.useState(""),[b,G]=g.useState(""),[_,ae]=g.useState(""),[te,de]=g.useState(""),[le,ne]=g.useState(""),[ie,ge]=g.useState(""),[me,Ce]=g.useState(!1),[F,ve]=g.useState("username"),[D,ee]=g.useState("0"),[oe,Ne]=g.useState(""),[Me,ue]=g.useState(!1),Q=m==="setup",re=m==="register",V=Ms(y?.registrationMode),A=re&&V==="email",Y=re&&V==="discord";async function p(){if(!Y){if((Q||re)&&le!==ie){Ne("两次输入的密码不一致");return}ue(!0),Ne("");try{const z=Q?"/api/auth/setup":re?"/api/auth/register":"/api/auth/login",$=A?cp(_):P,f=m==="login"?{identifier:P,password:le}:{username:$,password:le,displayName:b,email:_,discordUserId:Q?te:"",registrationEnabled:Q?me:void 0,registrationMode:Q?F:void 0,defaultBalance:Q?Number(D||0):void 0},N=await pe(z,{method:"POST",body:JSON.stringify(f)});K(N.session)}catch(z){Ne(z instanceof Error?z.message:"操作失败")}finally{ue(!1)}}}return n.jsxs("main",{className:"auth-page","data-theme":c,children:[n.jsxs("header",{className:"auth-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:O,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>r(c==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:c==="dark"?"sun":"moon"}),n.jsx("span",{children:c==="dark"?"浅色":"暗色"})]})]}),n.jsxs("section",{className:"auth-stage",children:[n.jsxs("div",{className:"auth-intro",children:[n.jsx("span",{children:Q?"First Run":"Welcome Back"}),n.jsx("h1",{children:Q?"初始化 CAPI":re?"创建账号":"登录"}),n.jsx("p",{children:Q?"创建第一个管理员账号,完成后即可进入控制台。":"使用你的 CAPI 账号继续。"})]}),n.jsxs("form",{className:"auth-form",onSubmit:z=>{z.preventDefault(),p()},children:[Y?n.jsxs("div",{className:"auth-discord-register",children:[n.jsx("strong",{children:"使用 Discord 创建账号"}),n.jsx("span",{children:"继续后会按站点设置校验服务器和身份组。"}),y?.discordEnabled?n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"继续使用 Discord"}):n.jsx("div",{className:"auth-message",children:"管理员还没有启用 Discord 登录"})]}):n.jsxs(n.Fragment,{children:[m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:b,onChange:z=>G(z.target.value),autoComplete:"name",placeholder:"CAPI"})]}),!A&&n.jsxs("label",{children:[n.jsx("span",{children:m==="login"?"账号或邮箱":"账号"}),n.jsx("input",{value:P,onChange:z=>T(z.target.value),autoComplete:"username",placeholder:m==="login"?"输入账号或邮箱":"3-32 位字母、数字、_ 或 -"})]}),(Q||A)&&n.jsxs("label",{children:[n.jsx("span",{children:A?"邮箱":"邮箱(可选)"}),n.jsx("input",{type:"email",value:_,onChange:z=>ae(z.target.value),autoComplete:"email",placeholder:"name@example.com"})]}),Q&&n.jsxs(n.Fragment,{children:[n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:te,onChange:z=>de(z.target.value),placeholder:"绑定管理员 Discord 账号"})]}),n.jsxs("div",{className:"setup-options",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放注册"}),n.jsx("button",{type:"button",className:me?"ios-switch is-on":"ios-switch","aria-pressed":me,onClick:()=>Ce(z=>!z),children:n.jsx("span",{})})]}),n.jsxs("label",{children:[n.jsx("span",{children:"注册方式"}),n.jsxs("select",{value:F,onChange:z=>ve(Ms(z.target.value)),children:[n.jsx("option",{value:"username",children:"账号密码"}),n.jsx("option",{value:"email",children:"邮箱"}),n.jsx("option",{value:"discord",children:"Discord"})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新用户初始额度"}),n.jsx("input",{type:"number",min:"0",step:"0.01",value:D,onChange:z=>ee(z.target.value)})]})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"密码"}),n.jsx("input",{type:"password",value:le,onChange:z=>ne(z.target.value),autoComplete:m==="login"?"current-password":"new-password",placeholder:"至少 8 个字符"})]}),m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"确认密码"}),n.jsx("input",{type:"password",value:ie,onChange:z=>ge(z.target.value),autoComplete:"new-password",placeholder:"再次输入密码"})]}),n.jsx("div",{className:"auth-message",role:"status",children:oe}),n.jsx("button",{className:"primary-button auth-submit",type:"submit",disabled:Me,children:Me?"请稍候":Q?"创建管理员":re?"注册":"登录"})]}),!Q&&!Y&&y?.discordEnabled&&n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"使用 Discord 登录"}),!Q&&n.jsx("div",{className:"auth-switch",children:m==="login"&&y?.registrationEnabled?n.jsx("button",{type:"button",onClick:()=>E("register"),children:"创建账号"}):n.jsx("button",{type:"button",onClick:()=>E("login"),children:"返回登录"})})]})]})]})}function dp({theme:c,setTheme:m,goHome:y,openLogin:r}){const[E,O]=g.useState(null),[K,P]=g.useState([]),[T,b]=g.useState(null),[G,_]=g.useState(!1),[ae,te]=g.useState(""),[de,le]=g.useState(""),[ne,ie]=g.useState("");async function ge(){try{const[D,ee,oe]=await Promise.all([pe("/api/account/me"),pe("/api/catalog/models"),pe("/api/account/check-in")]);O({...D,apiKeys:be(D.apiKeys)}),P(be(ee.models).map(ui)),b(oe.checkIn)}catch{r()}}g.useEffect(()=>{ge()},[]);async function me(){if(!(!T?.enabled||T.claimed||G)){_(!0),te("");try{const D=await pe("/api/account/check-in",{method:"POST",body:JSON.stringify({})});O(ee=>ee&&{...ee,user:D.user}),b(D.checkIn),te(`签到成功,获得 ${D.reward.toFixed(2)} 额度`)}catch(D){te(D instanceof Error?D.message:"签到失败,请稍后重试")}finally{_(!1)}}}async function Ce(){try{const D=await pe("/api/account/api-keys",{method:"POST",body:JSON.stringify({name:"My API Key"})});le(D.secret),ie("新密钥只显示这一次"),await ge()}catch(D){ie(D instanceof Error?D.message:"创建密钥失败")}}async function F(D){if(window.confirm("删除这个 API Key?使用它的请求会立即失效。"))try{await pe(`/api/account/api-keys/${D}`,{method:"DELETE"}),O(ee=>ee&&{...ee,apiKeys:ee.apiKeys.filter(oe=>oe.id!==D)}),ie("密钥已删除")}catch(ee){ie(ee instanceof Error?ee.message:"删除密钥失败")}}async function ve(){await pe("/api/auth/logout",{method:"POST"}),y()}return n.jsxs("main",{className:"account-page","data-theme":c,children:[n.jsxs("header",{className:"account-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:y,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("div",{className:"account-actions",children:[n.jsx("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(c==="dark"?"light":"dark"),children:n.jsx(Ot,{name:c==="dark"?"sun":"moon"})}),n.jsx("button",{className:"secondary-button",onClick:ve,children:"退出"})]})]}),n.jsxs("section",{className:"account-content",children:[n.jsxs("div",{className:"account-heading",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"My CAPI"}),n.jsx("h1",{children:E?.user.name||"账户"})]}),n.jsxs("div",{className:"account-balance",children:[n.jsx("span",{children:"余额"}),n.jsx("strong",{children:E?E.user.balance.toFixed(2):"-"})]})]}),n.jsxs("section",{className:"account-section check-in-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Daily Reward"}),n.jsx("h2",{children:"每日签到"})]}),n.jsx("button",{className:"primary-button",disabled:!T?.enabled||!!T?.claimed||G,onClick:me,children:G?"领取中":T?.claimed?"今日已签到":T?.enabled?"签到领额度":"暂未开放"})]}),n.jsxs("div",{className:"check-in-summary",children:[n.jsxs("div",{children:[n.jsx("span",{children:"今日状态"}),n.jsx("strong",{children:T?.claimed?`已领取 ${T.reward.toFixed(2)}`:T?.enabled?"等待签到":"活动关闭"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"随机奖励"}),n.jsx("strong",{children:T?`${T.minReward.toFixed(2)} - ${T.maxReward.toFixed(2)}`:"-"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"结算日期"}),n.jsx("strong",{children:T?.day||"北京时间"})]})]}),n.jsx("p",{className:"check-in-note",children:"每天按北京时间 00:00 刷新,奖励领取后直接计入账户余额。"}),ae&&n.jsx("p",{className:"account-message check-in-message",role:"status",children:ae})]}),n.jsxs("section",{className:"account-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"API Keys"}),n.jsx("h2",{children:"API 密钥"})]}),n.jsx("button",{className:"primary-button",onClick:Ce,children:"创建密钥"})]}),de&&n.jsx("code",{className:"one-time-secret",children:de}),ne&&n.jsx("p",{className:"account-message",children:ne}),n.jsxs("div",{className:"account-key-list",children:[E?.apiKeys?.map(D=>n.jsxs("div",{className:"account-key-item",children:[n.jsx("span",{className:"account-key-mark","aria-hidden":"true",children:n.jsx(Ot,{name:"key"})}),n.jsxs("div",{className:"account-key-info",children:[n.jsx("strong",{children:D.name}),n.jsxs("code",{children:[D.prefix,"…"]})]}),n.jsx(Dt,{tone:D.status,children:_t(D.status)}),n.jsx("button",{className:"icon-button","aria-label":`删除 ${D.name}`,title:"删除密钥",onClick:()=>F(D.id),children:n.jsx(Ot,{name:"ban"})})]},D.id)),be(E?.apiKeys).length===0&&n.jsx("div",{className:"empty",children:"还没有 API 密钥"})]})]}),n.jsxs("section",{className:"account-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Models"}),n.jsx("h2",{children:"可用模型"})]})}),n.jsxs("div",{className:"account-model-grid",children:[K.map(D=>n.jsxs("article",{children:[n.jsx("span",{children:D.vendor}),n.jsx("strong",{children:D.name}),n.jsx("p",{children:D.description}),n.jsx("code",{children:D.id})]},D.id)),K.length===0&&n.jsx("div",{className:"account-model-empty",children:"暂无可用模型,管理员配置渠道后将在此展示"})]})]})]})]})}function fp({theme:c,setTheme:m,enterConsole:y}){return n.jsxs("main",{className:"public-home","data-theme":c,children:[n.jsxs("header",{className:"home-topbar",children:[n.jsxs("div",{className:"home-brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"AI 聚合网关"})]})]}),n.jsxs("div",{className:"home-actions",children:[n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(c==="dark"?"light":"dark"),children:[n.jsx(Ot,{name:c==="dark"?"sun":"moon"}),n.jsx("span",{children:c==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:y,children:"控制台"})]})]}),n.jsxs("section",{className:"home-hero",children:[n.jsxs("div",{className:"home-copy",children:[n.jsx("span",{className:"home-kicker",children:"兼容 OpenAI 格式的网关"}),n.jsxs("h1",{children:["CAPI",n.jsx("span",{children:"轻量 AI 聚合网关"})]}),n.jsx("p",{children:"面向个人用户和团队的模型接入层。把 API Key、额度、模型渠道和调用日志放在一个清爽控制台里,保持轻量,也便于排障。"}),n.jsx("div",{className:"home-cta",children:n.jsx("button",{className:"primary-button",onClick:y,children:"进入控制台"})}),n.jsxs("div",{className:"integration-row","aria-label":"网关能力概览",children:[n.jsx("span",{children:"网关能力"}),n.jsxs("div",{children:[n.jsx("span",{children:"OpenAI 兼容接口"}),n.jsx("span",{children:"额度控制"}),n.jsx("span",{children:"调用审计"})]})]})]}),n.jsxs("div",{className:"gateway-terminal","aria-label":"CAPI 终端请求示意",children:[n.jsxs("div",{className:"terminal-titlebar",children:[n.jsxs("div",{className:"terminal-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsx("strong",{children:"CAPI Terminal"}),n.jsxs("div",{className:"terminal-status",children:[n.jsx("span",{className:"pulse-dot"}),n.jsx("strong",{children:"Online"})]})]}),n.jsxs("div",{className:"terminal-endpoint",children:[n.jsx("span",{children:"POST"}),n.jsx("strong",{children:"/v1/chat/completions"})]}),n.jsxs("div",{className:"terminal-body",children:[n.jsxs("div",{className:"terminal-block",children:[n.jsx("span",{children:"REQUEST"}),n.jsx("pre",{children:`curl https://api.capi.local/v1/chat/completions \\ + -H "Authorization: Bearer cat_..." \\ + -d '{ + "model": "capi-fast", + "messages": [{ "role": "user", "content": "ping" }] + }'`})]}),n.jsxs("div",{className:"terminal-route",children:[n.jsxs("div",{children:[n.jsx("span",{children:"auth"}),n.jsx("strong",{children:"pass"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"quota"}),n.jsx("strong",{children:"ok"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"route"}),n.jsx("strong",{children:"capi-fast"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"latency"}),n.jsx("strong",{children:"186ms"})]})]}),n.jsxs("div",{className:"terminal-block response",children:[n.jsx("span",{children:"RESPONSE"}),n.jsxs("pre",{children:[`{ + "status": 200, + "model": "capi-fast", + "usage": { "total_tokens": 27 }, + "message": "request routed" +}`,n.jsx("span",{className:"terminal-caret","aria-hidden":"true"})]})]})]})]})]})]})}function mp({overview:c,channels:m,logs:y,onNavigate:r}){const E=y.filter(O=>O.status!=="success");return n.jsxs("section",{className:"page-stack",children:[n.jsxs("div",{className:"hero-strip",children:[n.jsxs("div",{children:[n.jsx("span",{children:"Live Gateway"}),n.jsxs("strong",{children:["CAPI 网关正在服务 ",c?.activeUsers??"-"," 个活跃用户"]}),n.jsx("p",{children:"请求进入 CAPI 后,会按额度、模型和渠道状态自动选择最合适的上游。"})]}),n.jsxs("div",{className:"live-island",children:[n.jsx("div",{className:"pulse-dot"}),n.jsx("span",{children:"在线"})]})]}),n.jsxs("div",{className:"quick-actions","aria-label":"快捷操作",children:[n.jsx(Ss,{icon:"key",label:"创建 Key",onClick:()=>r("keys")}),n.jsx(Ss,{icon:"route",label:"配置渠道",onClick:()=>r("channels")}),n.jsx(Ss,{icon:"users",label:"调整额度",onClick:()=>r("users")}),n.jsx(Ss,{icon:"logs",label:"查看异常",onClick:()=>r("logs")})]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(ul,{label:"活跃用户",value:c?Ca(c.activeUsers):"-"}),n.jsx(ul,{label:"今日请求",value:c?Ca(c.requestsToday):"-"}),n.jsx(ul,{label:"今日输入",value:c?Ca(c.todayInputTokens):"-"}),n.jsx(ul,{label:"今日输出",value:c?Ca(c.todayOutputTokens):"-"}),n.jsx(ul,{label:"今日扣费",value:c?ci(c.todayCost,4):"-"}),n.jsx(ul,{label:"账户余额",value:c?ci(c.totalBalance):"-"}),n.jsx(ul,{label:"成功率",value:c?`${c.successRate}%`:"-"})]}),n.jsx(hp,{}),n.jsxs("div",{className:"split-grid",children:[n.jsx(lt,{title:"渠道状态",children:m.length?m.map(O=>n.jsxs("div",{className:"list-row overview-channel-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:O.name}),n.jsx("span",{title:be(O.models).join(", "),children:ip(O.models)})]}),n.jsx(Dt,{tone:O.status,children:_t(O.status)})]},O.id)):n.jsx(Qt,{text:"暂无渠道"})}),n.jsx(lt,{title:"最近请求",children:y.length?y.slice(0,4).map(O=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:to(O)}),n.jsxs("span",{children:[O.id," · ",O.errorCode||el(O.createdAt)]})]}),n.jsx(Dt,{tone:O.status,children:_t(O.status)})]},O.id)):n.jsx(Qt,{text:E.length?"暂无最近请求":"暂无请求"})})]})]})}function Ss({icon:c,label:m,onClick:y}){return n.jsxs("button",{className:"quick-action",onClick:y,children:[n.jsx(Ot,{name:c}),n.jsx("span",{children:m})]})}function hp(){const c=[{label:"认证",detail:"校验 API Key"},{label:"额度",detail:"检查余额"},{label:"路由",detail:"选择渠道"},{label:"响应",detail:"返回结果"}];return n.jsxs("section",{className:"flow-panel","aria-label":"网关流转",children:[n.jsxs("div",{className:"flow-copy",children:[n.jsx("span",{children:"Request Flow"}),n.jsx("strong",{children:"请求处理流程"})]}),n.jsx("div",{className:"flow-steps",children:c.map((m,y)=>n.jsxs("div",{className:"flow-step",children:[n.jsx("div",{className:"flow-index",children:y+1}),n.jsx("strong",{children:m.label}),n.jsx("span",{children:m.detail})]},m.label))})]})}function pp({users:c,query:m,selectedUser:y,onQuery:r,onSelect:E,onUpdate:O,onBulkUpdate:K,onCreateKey:P,groups:T,onOpenRegistration:b}){const[_,ae]=g.useState(1),[te,de]=g.useState("all"),[le,ne]=g.useState(new Set),[ie,ge]=g.useState("10"),[me,Ce]=g.useState(""),[F,ve]=g.useState(""),[D,ee]=g.useState(!1),[oe,Ne]=g.useState("10"),[Me,ue]=g.useState(""),[Q,re]=g.useState(""),[V,A]=g.useState(!1),Y=te==="all"?c:c.filter(M=>M.status===te),p=Y.filter(M=>M.role!=="admin"),z=Math.max(1,Math.ceil(Y.length/25)),$=Math.min(_,z),f=Y.slice(($-1)*25,$*25),N=p.length>0&&p.every(M=>le.has(M.id));g.useEffect(()=>{ae(1)},[m,te]),g.useEffect(()=>{const M=new Set(c.map(je=>je.id));ne(je=>new Set([...je].filter(Se=>M.has(Se))))},[c]),g.useEffect(()=>{Ne("10"),ue(""),re("")},[y?.user.id]);function q(M){ne(je=>{const Se=new Set(je);return Se.has(M)?Se.delete(M):Se.add(M),Se})}function L(){ne(M=>{const je=new Set(M);return N?p.forEach(Se=>je.delete(Se.id)):p.forEach(Se=>je.add(Se.id)),je})}async function Z(M,je){if(le.size!==0){ee(!0);try{await K([...le],M,je),ne(new Set),Ce("")}finally{ee(!1)}}}async function xe(M){if(!y)return;const je=Math.abs(Number(oe));if(!Number.isFinite(je)||je<=0){re("请输入大于 0 的金额");return}A(!0),re("");try{await K([y.user.id],"adjust_balance",{amount:Number((je*M).toFixed(4)),reason:Me.trim()||(M>0?"管理员增加额度":"管理员扣减额度")}),re(M>0?"额度已增加":"额度已扣减"),ue("")}catch(Se){re(Se instanceof Error?Se.message:"额度调整失败")}finally{A(!1)}}return n.jsxs("section",{className:"users-layout",children:[n.jsxs(lt,{title:"用户管理",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:m,onChange:M=>r(M.target.value),placeholder:"搜索 ID、姓名或邮箱"})]}),n.jsx("button",{className:"icon-button",title:"开放注册",onClick:b,children:n.jsx(Ot,{name:"plus"})})]}),n.jsxs("div",{className:"user-summary-strip",children:[n.jsxs("span",{children:[n.jsx("strong",{children:c.length})," 匹配用户"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.filter(M=>M.status==="active").length})," 正常"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.filter(M=>M.status==="disabled").length})," 禁用"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.reduce((M,je)=>M+je.requestsToday,0)})," 今日请求"]})]}),n.jsx("div",{className:"user-filter-row",role:"group","aria-label":"用户状态筛选",children:[{value:"all",label:"全部"},{value:"active",label:"正常"},{value:"limited",label:"受限"},{value:"disabled",label:"禁用"}].map(M=>n.jsx("button",{type:"button",className:te===M.value?"selected":"",onClick:()=>de(M.value),children:M.label},M.value))}),n.jsx("button",{type:"button",className:"secondary-button mobile-bulk-select",onClick:L,children:N?"取消全选":`全选结果(${p.length})`}),le.size>0&&n.jsxs("div",{className:"bulk-action-bar",children:[n.jsxs("strong",{children:["已选 ",le.size," 人"]}),n.jsx("input",{type:"number",step:"0.01",value:ie,onChange:M=>ge(M.target.value),"aria-label":"额度调整值"}),n.jsx("input",{value:me,onChange:M=>Ce(M.target.value),placeholder:"原因,例如:活动赠送","aria-label":"调整原因"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D||!Number(ie),onClick:()=>Z("adjust_balance",{amount:Number(ie),reason:me}),children:"调整额度"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D,onClick:()=>Z("set_status",{value:"active"}),children:"启用"}),n.jsx("button",{type:"button",className:"danger-button",disabled:D,onClick:()=>Z("set_status",{value:"disabled"}),children:"禁用"}),n.jsxs("select",{className:"bulk-group-select",value:F,disabled:D,"aria-label":"批量设置分组",onChange:M=>ve(M.target.value),children:[n.jsx("option",{value:"",children:"未分组"}),T.map(M=>n.jsx("option",{value:M.id,children:M.name},M.id))]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:D,onClick:()=>Z("set_group",{value:F}),children:"设为分组"})]}),n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head users-table",children:[n.jsx("input",{type:"checkbox",checked:N,onChange:L,"aria-label":"选择当前筛选结果"}),n.jsx("span",{children:"用户"}),n.jsx("span",{children:"状态"}),n.jsx("span",{children:"余额"}),n.jsx("span",{children:"今日"})]}),f.map(M=>n.jsxs("div",{className:y?.user.id===M.id?"table-row users-table selected":"table-row users-table",role:"button",tabIndex:0,onClick:()=>E(M.id),onKeyDown:je=>{(je.key==="Enter"||je.key===" ")&&E(M.id)},children:[n.jsx("input",{type:"checkbox",checked:le.has(M.id),disabled:M.role==="admin",onChange:()=>q(M.id),onClick:je=>je.stopPropagation(),"aria-label":M.role==="admin"?`${M.name} 是管理员,不参与批量操作`:`选择 ${M.name}`}),n.jsxs("span",{children:[n.jsx("strong",{children:M.name}),n.jsxs("small",{children:[M.id," · ",M.email||"未绑定邮箱"]})]}),n.jsx(Dt,{tone:M.status,children:_t(M.status)}),n.jsx("span",{children:ci(M.balance)}),n.jsx("span",{children:M.requestsToday})]},M.id)),Y.length===0&&n.jsx(Qt,{text:"暂无匹配用户"})]}),Y.length>25&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:$<=1,onClick:()=>ae(M=>Math.max(1,M-1)),children:"上一页"}),n.jsxs("span",{children:[$," / ",z]}),n.jsx("button",{className:"secondary-button",disabled:$>=z,onClick:()=>ae(M=>Math.min(z,M+1)),children:"下一页"})]})]}),n.jsx(lt,{title:"用户详情",children:y?n.jsxs("div",{className:"detail-stack",children:[n.jsxs("div",{className:"user-hero",children:[n.jsx("div",{className:"avatar",children:y.user.name.slice(0,1)}),n.jsxs("div",{children:[n.jsx("h2",{children:y.user.name}),n.jsx("p",{children:y.user.email})]}),n.jsx(Dt,{tone:y.user.status,children:_t(y.user.status)})]}),n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"角色",value:y.user.role==="admin"?"管理员":"用户"}),n.jsx(Pt,{label:"余额",value:ci(y.user.balance)}),n.jsx(Pt,{label:"总请求",value:String(y.user.totalRequests)}),n.jsx(Pt,{label:"最后登录",value:el(y.user.lastLoginAt)}),n.jsx(Pt,{label:"API 调用",value:y.user.status==="disabled"?"关闭":"允许",switchOn:y.user.status!=="disabled"})]}),n.jsxs("div",{className:"group-assign-row",children:[n.jsxs("label",{children:[n.jsx("span",{children:"所属分组"}),n.jsxs("select",{value:y.user.groupId||"",onChange:M=>O(y.user.id,{groupId:M.target.value}),children:[n.jsx("option",{value:"",children:"未分组"}),T.map(M=>n.jsx("option",{value:M.id,children:M.name},M.id))]})]}),n.jsx("small",{children:"分组决定该用户可路由到哪些渠道;未分组用户只能使用未限制分组的渠道。"})]}),n.jsxs("div",{className:"balance-adjuster",children:[n.jsxs("div",{className:"balance-adjuster-title",children:[n.jsx("strong",{children:"调整余额"}),n.jsxs("span",{children:["当前 ",ci(y.user.balance)]})]}),n.jsxs("div",{className:"balance-adjuster-fields",children:[n.jsxs("label",{children:[n.jsx("span",{children:"金额"}),n.jsx("input",{type:"number",min:"0.0001",step:"0.01",value:oe,onChange:M=>Ne(M.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"备注"}),n.jsx("input",{value:Me,onChange:M=>ue(M.target.value),placeholder:"可选,会记录到流水"})]})]}),n.jsxs("div",{className:"balance-adjuster-actions",children:[n.jsx("button",{className:"secondary-button",disabled:V,onClick:()=>xe(1),children:"增加"}),n.jsx("button",{className:"danger-button",disabled:V,onClick:()=>xe(-1),children:"扣减"}),n.jsx("span",{role:"status",children:Q})]})]}),n.jsxs("div",{className:"action-row",children:[n.jsx("button",{className:"secondary-button",onClick:()=>P(y.user.id),children:"创建 Key"}),n.jsx("button",{className:"secondary-button",disabled:y.user.role==="admin",onClick:()=>O(y.user.id,{status:y.user.status==="disabled"?"active":"disabled"}),children:y.user.role==="admin"?"管理员保护":y.user.status==="disabled"?"解封":"禁用"})]}),n.jsxs("div",{children:[n.jsx("h3",{children:"API Key"}),y.apiKeys.map(M=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:M.name}),n.jsxs("span",{children:[M.prefix,"*** · ",M.requestCount," 次"]})]}),n.jsx(Dt,{tone:M.status,children:_t(M.status)})]},M.id)),y.apiKeys.length===0&&n.jsx(Qt,{text:"暂无 API Key"})]})]}):n.jsx(Qt,{text:"请选择一个用户"})})]})}function vp({selectedUser:c,onCreateKey:m,onUpdateKey:y,onDeleteKey:r}){return n.jsx(lt,{title:"密钥管理",children:c?n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("span",{className:"muted-inline",children:[c.user.name," · 完整 Key 只在创建时显示,丢失请重新创建"]}),n.jsx("button",{className:"primary-button",onClick:()=>m(c.user.id),children:"创建 Key"})]}),c.apiKeys.length?c.apiKeys.map(E=>n.jsx(yp,{apiKey:E,onSave:y,onDelete:r},E.id)):n.jsx(Qt,{text:"暂无密钥"})]}):n.jsx(Qt,{text:"请选择一个用户"})})}function yp({apiKey:c,onSave:m,onDelete:y}){const[r,E]=g.useState(c.name),[O,K]=g.useState(be(c.allowedModels).join(", ")),[P,T]=g.useState(fm(c.expiresAt||"")),[b,G]=g.useState(String(c.rateLimitPerMinute||"")),[_,ae]=g.useState(!1),te=be(c.allowedModels).length?be(c.allowedModels).join(", "):"全部模型";g.useEffect(()=>{E(c.name),K(be(c.allowedModels).join(", ")),T(fm(c.expiresAt||"")),G(String(c.rateLimitPerMinute||""))},[c]);async function de(){ae(!0);try{await m(c.id,{name:r.trim()||"API Key",allowedModels:Ic(O),expiresAt:tp(P),rateLimitPerMinute:Number(b||0)})}finally{ae(!1)}}return n.jsxs("details",{className:"key-editor key-editor-collapsible",children:[n.jsxs("summary",{className:"key-editor-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:c.name}),n.jsxs("span",{children:[c.prefix,"*** · ",te," · 最后使用 ",el(c.lastUsedAt)]})]}),n.jsxs("div",{className:"row-actions",children:[n.jsx(Dt,{tone:c.status,children:_t(c.status)}),n.jsx("span",{className:"key-expand-hint",children:"管理"})]})]}),n.jsxs("div",{className:"key-editor-body",children:[n.jsxs("div",{className:"key-editor-grid",children:[n.jsxs("label",{children:["名称",n.jsx("input",{value:r,onChange:le=>E(le.target.value)})]}),n.jsxs("label",{children:["允许模型",n.jsx("input",{value:O,onChange:le=>K(le.target.value),placeholder:"留空表示全部模型,多个用逗号分隔"})]}),n.jsxs("label",{children:["过期时间",n.jsx("input",{type:"datetime-local",value:P,onChange:le=>T(le.target.value)})]}),n.jsxs("label",{children:["每分钟限制",n.jsx("input",{type:"number",min:"0",value:b,onChange:le=>G(le.target.value),placeholder:"0 使用全局限制"})]})]}),n.jsxs("div",{className:"key-editor-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>m(c.id,{status:c.status==="active"?"disabled":"active"}),children:c.status==="active"?"停用密钥":"启用密钥"}),n.jsx("button",{className:"danger-button",onClick:()=>y(c.id),children:"删除密钥"}),n.jsx("button",{className:"primary-button",disabled:_,onClick:de,children:_?"保存中":"保存设置"})]})]})]})}function bp({models:c,onCopy:m,onCreate:y,onUpdate:r,onDelete:E}){const O=c.filter(p=>p.recommended),[K,P]=g.useState(""),[T,b]=g.useState("all"),[G,_]=g.useState("all"),[ae,te]=g.useState(1),[de,le]=g.useState(""),[ne,ie]=g.useState(""),[ge,me]=g.useState(""),[Ce,F]=g.useState(""),[ve,D]=g.useState(""),[ee,oe]=g.useState(""),Ne=60,Me=g.useMemo(()=>{const p=new Map;return c.forEach(z=>{const $=$c(z);p.set($,(p.get($)||0)+1)}),Array.from(p.entries()).sort((z,$)=>$[1]-z[1]||sl(z[0]).localeCompare(sl($[0]))).map(([z,$])=>({provider:z,count:$}))},[c]),ue=g.useMemo(()=>{const p=K.trim().toLowerCase();return c.filter(z=>T!=="all"&&$c(z)!==T||G!=="all"&&z.status!==G?!1:p?[z.id,z.name,z.vendor,z.category,z.description,...be(z.aliases)].join(" ").toLowerCase().includes(p):!0)},[c,K,T,G]),Q=g.useMemo(()=>{const p=new Map;ue.forEach(q=>{const L=$c(q);p.set(L,[...p.get(L)||[],q])});const z=[];let $=[],f=0;const N=Array.from(p.entries()).sort((q,L)=>sl(q[0]).localeCompare(sl(L[0])));for(const q of N)$.length>0&&f+q[1].length>Ne&&(z.push($),$=[],f=0),$.push(q),f+=q[1].length;return $.length>0&&z.push($),z},[ue]),re=Math.max(1,Q.length),V=Math.min(ae,re),A=Q[V-1]||[];g.useEffect(()=>{te(1)},[K,T,G,c.length]);async function Y(p){p.preventDefault();const z=de.trim();if(z){oe("");try{await y({id:z,name:ne.trim()||z,vendor:ge.trim()||"Custom",aliases:Ce.split(",").map($=>$.trim()).filter(Boolean),category:"通用",description:ve.trim(),price:"自定义",context:"未配置上下文"}),le(""),ie(""),me(""),F(""),D("")}catch($){oe($ instanceof Error?$.message:"模型添加失败")}}}return n.jsxs("section",{className:"models-page",children:[n.jsx("div",{className:"model-hero",children:n.jsxs("div",{children:[n.jsx("span",{children:"Model Catalog"}),n.jsx("strong",{children:"Models"})]})}),n.jsx(lt,{title:"新增模型",children:n.jsxs("form",{className:"model-create-form",onSubmit:Y,children:[n.jsx("input",{value:de,onChange:p=>le(p.target.value),placeholder:"模型 ID,例如 openai/gpt-4.1"}),n.jsx("input",{value:ne,onChange:p=>ie(p.target.value),placeholder:"显示名称(可选)"}),n.jsx("input",{value:ge,onChange:p=>me(p.target.value),placeholder:"供应商(可选)"}),n.jsx("input",{value:Ce,onChange:p=>F(p.target.value),placeholder:"代称,多个用逗号分隔(可选)"}),n.jsx("input",{className:"model-create-wide",value:ve,onChange:p=>D(p.target.value),placeholder:"描述(可选)"}),n.jsx("button",{className:"primary-button",type:"submit",children:"新增模型"}),n.jsx("div",{className:"model-create-message",role:"status",children:ee})]})}),O.length>0&&n.jsx(lt,{title:"推荐模型",children:n.jsx("div",{className:"model-grid",children:O.map(p=>n.jsx(xp,{model:p,featured:!0,onCopy:m,onUpdate:r},p.id))})}),n.jsxs(lt,{title:"全部模型",children:[n.jsxs("div",{className:"panel-toolbar model-list-toolbar",children:[n.jsx("input",{value:K,onChange:p=>P(p.target.value),placeholder:"搜索模型 ID、名称、供应商或代称"}),n.jsx("div",{className:"model-filter-actions",children:[{value:"all",label:"全部"},{value:"available",label:"可用"},{value:"disabled",label:"禁用"}].map(p=>n.jsx("button",{type:"button",className:G===p.value?"selected":"",onClick:()=>_(p.value),children:p.label},p.value))})]}),n.jsxs("div",{className:"model-provider-filter","aria-label":"按供应商筛选模型",children:[n.jsxs("button",{type:"button",className:T==="all"?"selected":"",onClick:()=>b("all"),children:[n.jsx("span",{className:"provider-icon provider-icon-all","aria-hidden":"true",children:"All"}),n.jsx("strong",{children:"全部"}),n.jsx("small",{children:c.length})]}),Me.map(p=>n.jsxs("button",{type:"button",className:T===p.provider?"selected":"",onClick:()=>b(p.provider),children:[n.jsx(mm,{provider:p.provider}),n.jsx("strong",{children:sl(p.provider)}),n.jsx("small",{children:p.count})]},p.provider))]}),n.jsxs("div",{className:"model-list-summary",children:[n.jsx("span",{children:T==="all"?"全部供应商":sl(T)}),n.jsx("strong",{children:ue.length}),n.jsx("span",{children:"个模型"})]}),ue.length>0?n.jsxs(n.Fragment,{children:[n.jsx("div",{className:"model-provider-groups",children:A.map(([p,z])=>n.jsxs("section",{className:"model-provider-group",children:[n.jsxs("header",{children:[n.jsx(mm,{provider:p}),n.jsxs("div",{children:[n.jsx("strong",{children:sl(p)}),n.jsxs("span",{children:[z.length," 个模型"]})]})]}),n.jsx("div",{className:"model-compact-grid",children:z.map($=>n.jsx(gp,{model:$,onCopy:m,onUpdate:r,onDelete:E},$.id))})]},p))}),re>1&&n.jsxs("div",{className:"pager",children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>te(p=>Math.max(1,p-1)),disabled:V<=1,children:"上一页"}),n.jsxs("span",{children:[V," / ",re]}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>te(p=>Math.min(re,p+1)),disabled:V>=re,children:"下一页"})]})]}):n.jsx(Qt,{text:c.length?"没有匹配的模型":"暂无模型,请先添加你要开放给用户调用的模型 ID"})]})]})}function gp({model:c,onCopy:m,onUpdate:y,onDelete:r}){const E=be(c.aliases).slice(0,3),O=c.status==="disabled";return n.jsxs("article",{className:"model-compact-row",children:[n.jsxs("div",{className:"model-compact-main",children:[n.jsx("strong",{children:c.name}),n.jsx("small",{children:c.id}),E.length>0&&n.jsx("span",{children:E.map(K=>n.jsx("em",{children:K},K))})]}),n.jsxs("div",{className:"model-row-actions",children:[n.jsx(Dt,{tone:c.status,children:_t(c.status)}),c.recommended&&n.jsx("span",{className:"model-recommended-mark",children:"推荐"}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>m(c.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})}),n.jsxs("details",{className:"model-row-menu",children:[n.jsx("summary",{"aria-label":"模型操作",children:"•••"}),n.jsxs("div",{children:[n.jsx("button",{type:"button",onClick:()=>y(c.id,{recommended:!c.recommended}),children:c.recommended?"取消推荐":"设为推荐"}),n.jsx("button",{type:"button",onClick:()=>y(c.id,{status:O?"available":"disabled"}),children:O?"启用模型":"停用模型"}),n.jsx("button",{className:"is-danger",type:"button",onClick:()=>r(c.id),children:"删除模型"})]})]})]})]})}function xp({model:c,featured:m=!1,onCopy:y,onUpdate:r}){return n.jsxs("article",{className:m?"model-card featured":"model-card",children:[n.jsxs("div",{className:"model-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:c.name}),n.jsxs("span",{children:[c.vendor," · ",c.category]})]}),n.jsx(Dt,{tone:c.status,children:_t(c.status)})]}),n.jsx("p",{children:c.description}),n.jsx("div",{className:"alias-row",children:be(c.aliases).map(E=>n.jsx("span",{children:E},E))}),n.jsxs("div",{className:"model-meta",children:[n.jsxs("span",{children:["价格:",c.price]}),n.jsx("span",{children:c.context})]}),n.jsxs("div",{className:"model-id",children:[n.jsx("code",{children:c.id}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>y(c.id,"模型 ID 已复制"),children:n.jsx(Ot,{name:"copy"})})]}),r&&n.jsxs("div",{className:"model-card-actions",children:[n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(c.id,{recommended:!1}),children:"取消推荐"}),n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(c.id,{status:c.status==="disabled"?"available":"disabled"}),children:c.status==="disabled"?"启用":"停用"})]})]})}function jp({channels:c,onCreate:m,onImport:y,onCheckAccounts:r,onDeduplicateAccounts:E,onDeleteAccount:O,onUpdate:K,onStartOAuth:P,onCompleteOAuth:T}){const b=c.filter(p=>p.provider==="codex"||p.provider==="openai"||be(p.models).some(z=>z.includes("image"))),[G,_]=g.useState(""),[ae,te]=g.useState({}),[de,le]=g.useState({}),[ne,ie]=g.useState({}),[ge,me]=g.useState({}),[Ce,F]=g.useState(""),[ve,D]=g.useState(""),[ee,oe]=g.useState(""),Ne=24,Me=48;async function ue(p,z){_(`import:${p}`);try{await y(p,z)}finally{_("")}}async function Q(p,z=!1,$=""){_($?`check-account:${$}`:`${z?"retry":"check"}:${p}`);try{await r(p,z,$)}finally{_("")}}async function re(p){_(`dedupe:${p}`);try{await E(p)}finally{_("")}}function V(p){const z=be(p.openaiAccounts).map(Z=>[Z.email||Z.name||Z.accountId||Z.id,Z.accountId||"",Z.status||"unchecked",Z.credentialMode||"access-token",Z.planType||"",Z.expiresAt||"",Z.lastCheckedAt||"",Z.lastUsedAt||"",String(Z.requestCount||0),Z.lastErrorCode||"",Z.lastError||""]),$=Z=>`"${Z.replace(/"/g,'""')}"`,f=[["账号","Account ID","状态","凭据方式","套餐","到期时间","最近检测","最近调用","调用次数","错误码","最后错误"],...z].map(Z=>Z.map($).join(",")).join(`\r +`),N=new Blob(["\uFEFF"+f],{type:"text/csv;charset=utf-8"}),q=URL.createObjectURL(N),L=document.createElement("a");L.href=q,L.download=`${p.name||"account-pool"}-health-report.csv`,L.click(),URL.revokeObjectURL(q)}async function A(p){_(`status:${p.id}`);try{await K(p.id,{status:p.status==="disabled"?"healthy":"disabled",baseUrl:p.baseUrl||Es(p.provider)||Ts,provider:p.provider||"codex",models:be(p.models).length?p.models:bm.split(",").map(z=>z.trim())})}finally{_("")}}async function Y(p,z){const $=z.email||z.name||z.accountId||z.id;if(window.confirm(`删除账号「${$}」?`)){_(`delete-account:${z.id}`);try{await O(p.id,z.id)}finally{_("")}}}return n.jsxs(lt,{title:"账号池",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"账号有两种来源,任选其一即可。"}),n.jsx("button",{className:"primary-button",onClick:()=>m(gm("codex")),children:"新增账号池渠道"})]}),n.jsxs("div",{className:"source-guide",children:[n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"网页会话(推荐)"}),n.jsx("span",{children:"支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。"})]}),n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"批量导入"}),n.jsx("span",{children:"支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。"})]})]}),n.jsxs("div",{className:"channels-stack",children:[b.map(p=>{const z=be(p.openaiAccounts),$=z.filter(k=>k.status==="healthy").length,f=z.filter(k=>k.status==="invalid").length,N=z.filter(k=>!!k.lastErrorCode).length,q=Math.max(0,z.length-$-f),L=z.filter(k=>k.credentialMode==="refreshable").length,Z=z.filter(k=>k.credentialMode==="browser-session").length,xe=Math.max(0,z.length-L-Z),M=de[p.id]||"all",je=(ne[p.id]||"").trim().toLowerCase(),Se=z.filter(k=>{const mt=M==="all"||M==="attention"&&Op(k)||M==="invalid"&&k.status==="invalid"||M==="error"&&!!k.lastErrorCode||M==="refreshable"&&k.credentialMode==="refreshable",Ut=`${k.email||""} ${k.name||""} ${k.accountId||""} ${k.userId||""} ${k.lastError||""}`.toLowerCase();return mt&&(!je||Ut.includes(je))}),ot=ge[p.id]||"pool",J=[...Se].sort((k,mt)=>{if(ot==="pool")return 0;const Ut=ot==="expiry"?k.expiresAt||"9999-12-31":k.lastUsedAt||"",R=ot==="expiry"?mt.expiresAt||"9999-12-31":mt.lastUsedAt||"";return ot==="recent"?R.localeCompare(Ut):Ut.localeCompare(R)}),Je=Math.min(J.length,ae[p.id]||Ne),ut=J.slice(0,Je),Ie=Math.max(0,J.length-ut.length),tl=Ie===0;return n.jsxs("div",{className:"channel-card",children:[n.jsxs("div",{className:"channel-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:p.name}),n.jsx("span",{children:p.baseUrl||Es(p.provider)||Ts}),n.jsxs("small",{children:["账号 ",z.length," 个,可用 ",$,",无效 ",f,",未验证 ",q]}),n.jsxs("small",{children:["可续期 ",L," · 网页会话 ",Z," · 仅 Token ",xe]}),n.jsxs("small",{children:["自动检测 ",p.lastCheckedAt?el(p.lastCheckedAt):"等待首次检测"]})]}),n.jsxs("div",{className:"channel-card-head-actions",children:[n.jsx(Dt,{tone:p.status,children:_t(p.status)}),n.jsx("button",{className:"primary-button compact-button",onClick:()=>oe(p.id),disabled:G!=="",children:"添加账号"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>Q(p.id),disabled:G!==""||z.length===0,children:G===`check:${p.id}`?"检测中":"批量检测"}),f>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>Q(p.id,!0),disabled:G!=="",children:G===`retry:${p.id}`?"复检中":`复检无效 ${f}`}),z.length>1&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>re(p.id),disabled:G!=="",children:G===`dedupe:${p.id}`?"去重中":"账号去重"}),z.length>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>V(p),disabled:G!=="",children:"导出报告"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>A(p),disabled:G!=="",children:p.status==="disabled"?"启用渠道":"停用渠道"})]})]}),n.jsxs("div",{className:"account-filter-bar",role:"group","aria-label":"账号筛选",children:[n.jsx("input",{value:ne[p.id]||"",onChange:k=>ie(mt=>({...mt,[p.id]:k.target.value})),placeholder:"搜索账号或错误","aria-label":"搜索账号"}),n.jsxs("select",{value:ot,onChange:k=>me(mt=>({...mt,[p.id]:k.target.value})),"aria-label":"账号排序",children:[n.jsx("option",{value:"pool",children:"账号池顺序"}),n.jsx("option",{value:"oldest",children:"最久未用优先"}),n.jsx("option",{value:"recent",children:"最近使用优先"}),n.jsx("option",{value:"expiry",children:"最早到期优先"})]}),[["all",`全部 ${z.length}`],["attention","需关注"],["invalid",`无效 ${f}`],["error",`有错误 ${N}`],["refreshable",`可续期 ${L}`]].map(([k,mt])=>n.jsx("button",{type:"button",className:M===k?"selected":"",onClick:()=>le(Ut=>({...Ut,[p.id]:k})),children:mt},k))]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(ul,{label:"账号总数",value:z.length}),n.jsx(ul,{label:"可用账号",value:$}),n.jsx(ul,{label:"无效账号",value:f}),n.jsx(ul,{label:"未验证账号",value:q})]}),n.jsx("div",{className:"drawing-channel-models",children:be(p.models).length?be(p.models).map(k=>n.jsx("span",{children:k},k)):n.jsx("span",{children:"未绑定绘图模型"})}),z.length>0&&n.jsxs("div",{className:"account-pool-list",children:[ut.map(k=>n.jsxs("div",{className:"account-pool-row",children:[n.jsxs("div",{className:"account-pool-main",children:[n.jsxs("div",{children:[n.jsxs("div",{className:"account-pool-title",children:[n.jsx("strong",{title:k.email||k.name||k.accountId||k.id,children:k.email||k.name||k.accountId||k.id}),n.jsx("span",{className:`source-tag source-tag-${k.source==="web-login"?"web":"manual"}`,children:k.source==="web-login"?"网页登录":k.source==="web-oauth"?"网页 OAuth":k.source==="oauth"?"Codex OAuth":"导入"})]}),n.jsx("span",{children:k.lastError?`${dm(k.lastErrorCode)}${dm(k.lastErrorCode)?" · ":""}${k.lastError}`:k.lastCheckedAt?`上次检测 ${el(k.lastCheckedAt)}`:"未检测"}),n.jsxs("span",{children:[k.credentialMode==="refreshable"?"可自动续期":k.credentialMode==="browser-session"?"依赖网页会话":"仅 access token",k.expiresAt?` · 到期 ${el(k.expiresAt)}`:""]}),n.jsxs("span",{children:["套餐 ",P0(k.planType)]}),k.lastUsedAt&&n.jsxs("span",{children:["最近调用 ",el(k.lastUsedAt)," · ",k.requestCount||0," 次"]})]}),n.jsx(Tp,{limits:k.quotaLimits})]}),n.jsxs("div",{className:"account-pool-meta",children:[n.jsx(Dt,{tone:k.status==="healthy"?"healthy":k.status==="invalid"?"disabled":"standby",children:k.status==="healthy"?"可用":k.status==="invalid"?"无效":"未验证"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",disabled:G!=="",onClick:()=>Q(p.id,!1,k.id),children:G===`check-account:${k.id}`?"检测中":"检测"}),n.jsx("button",{type:"button",className:"danger-button compact-button",disabled:G!=="",onClick:()=>Y(p,k),children:G===`delete-account:${k.id}`?"删除中":"删除"})]})]},k.id)),Se.length===0&&n.jsx(Qt,{text:"没有匹配的账号"}),J.length>Ne&&n.jsxs("div",{className:"account-pool-more",children:[n.jsx("span",{className:"muted-inline",children:tl?`已显示全部 ${J.length} 个账号`:`已显示 ${ut.length} 个,还有 ${Ie} 个`}),n.jsxs("div",{className:"account-pool-more-actions",children:[!tl&&n.jsxs("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(k=>({...k,[p.id]:Math.min(J.length,Je+Me)})),children:["再显示 ",Math.min(Me,Ie)," 个"]}),!tl&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(k=>({...k,[p.id]:J.length})),children:"全部显示"}),Je>Ne&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(k=>({...k,[p.id]:Ne})),children:"收起"})]})]})]})]},p.id)}),b.length===0&&n.jsx(Qt,{text:"暂无绘图渠道,先新增一个 OpenAI 账号池渠道"})]}),Ce&&n.jsx(Cp,{channelId:Ce,onStart:P,onComplete:T,onClose:()=>F("")}),ee&&n.jsx(Sp,{busy:G!=="",onAuthSession:()=>{D(ee),oe("")},onImport:async p=>{await ue(ee,p),oe("")},onClose:()=>oe("")}),ve&&n.jsx(Ap,{onImport:async p=>{await ue(ve,new File([JSON.stringify(Np(p))],"authsession.json",{type:"application/json"}))},onClose:()=>D("")})]})}function Sp({busy:c,onAuthSession:m,onImport:y,onClose:r}){return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card account-add-modal",onClick:E=>E.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"添加账号"}),n.jsx("span",{children:"选择一种账号接入方式"})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsxs("div",{className:"account-add-options",children:[n.jsxs("button",{type:"button",className:"account-add-option recommended",onClick:m,disabled:c,children:[n.jsx("span",{className:"account-add-icon",children:"A"}),n.jsx("strong",{children:"导入网页会话"}),n.jsx("small",{children:"粘贴完整 authsession JSON,保留 sessionToken"})]}),n.jsxs("label",{className:`account-add-option${c?" disabled":""}`,children:[n.jsx("span",{className:"account-add-icon",children:"J"}),n.jsx("strong",{children:c?"导入中":"导入 JSON / ZIP / TXT"}),n.jsx("small",{children:"批量导入已有账号文件"}),n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:c,onChange:E=>{const O=E.target.files?.[0];O&&y(O),E.target.value=""}})]})]}),n.jsx("div",{className:"modal-actions",children:n.jsx("button",{type:"button",className:"secondary-button",onClick:r,children:"取消"})})]})})}function Np(c){const m=c.trim(),y=m.match(/(?:^|[;\s])(__Secure-(?:next-auth|authjs)\.session-token)=([^;\s]+)/);if(y)return{sessionToken:y[2],source:"web-login"};try{const r=JSON.parse(m),E=r.tokens&&typeof r.tokens=="object"?r.tokens:{},O=G=>typeof r[G]=="string"?r[G]:typeof E[G]=="string"?E[G]:"",K=O("accessToken")||O("access_token"),P=O("refreshToken")||O("refresh_token"),T=O("sessionToken")||O("session_token"),b=r.user&&typeof r.user=="object"?r.user:{};if(K||P||T)return{accessToken:K||void 0,refreshToken:P||void 0,sessionToken:T||void 0,email:typeof b.email=="string"?b.email:void 0,name:typeof b.name=="string"?b.name:void 0,source:"web-login"}}catch{}return{sessionToken:m,source:"web-login"}}function Ap({onImport:c,onClose:m}){const[y,r]=g.useState(""),[E,O]=g.useState(!1),[K,P]=g.useState(""),[T,b]=g.useState("");async function G(){if(!y.trim()){P("请粘贴 authsession");return}O(!0),P(""),b("");try{await c(y.trim()),r(""),b("已导入,继续粘贴下一条即可")}catch(_){P(_ instanceof Error?_.message:"导入失败")}finally{O(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:m,children:n.jsxs("div",{className:"modal-card",onClick:_=>_.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"添加网页会话"}),n.jsx("button",{type:"button",className:"icon-button",onClick:m,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["可直接粘贴 chatgpt.com/api/auth/session 的完整 JSON;也支持浏览器 ",n.jsx("code",{children:"__Secure-next-auth.session-token"})," 的值或完整 Cookie 字符串。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"authsession"}),n.jsx("textarea",{autoFocus:!0,value:y,onChange:_=>r(_.target.value),placeholder:"eyJhbGci..."})]}),K&&n.jsx("div",{className:"form-error",children:K}),T&&n.jsx("div",{className:"form-success",children:T}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:m,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:E,onClick:G,children:E?"导入中":"导入账号"})]})]})})}function Cp({channelId:c,onStart:m,onComplete:y,onClose:r}){const[E,O]=g.useState(""),[K,P]=g.useState(""),[T,b]=g.useState(""),[G,_]=g.useState(!1),[ae,te]=g.useState("");async function de(){_(!0),te("");try{const ne=await m(c);O(ne.authorizeUrl),P(ne.state),window.open(ne.authorizeUrl,"_blank","noopener")}catch(ne){te(ne instanceof Error?ne.message:"发起授权失败")}finally{_(!1)}}async function le(){if(!T.trim()){te("请粘贴授权完成后浏览器跳转的回调地址");return}_(!0),te("");try{await y(c,{callbackUrl:T.trim(),state:K}),r()}catch(ne){te(ne instanceof Error?ne.message:"完成授权失败")}finally{_(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card",onClick:ne=>ne.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"OAuth 授权添加网页账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsx("p",{className:"muted-inline",children:"使用 ChatGPT 网页兼容的 OAuth 客户端获取 refresh_token,只调用网页 backend-api,不会走 Codex 接口。"}),n.jsxs("ol",{className:"oauth-steps",children:[n.jsxs("li",{children:[n.jsx("button",{type:"button",className:"primary-button",onClick:de,disabled:G,children:E?"重新生成授权链接":"① 生成授权链接并打开"}),E&&n.jsxs("div",{className:"oauth-link",children:[n.jsx("input",{readOnly:!0,value:E,onFocus:ne=>ne.target.select()}),n.jsx("span",{className:"muted-inline",children:"若未自动打开,复制到浏览器手动访问,用要添加的 ChatGPT 账号登录授权。"})]})]}),n.jsxs("li",{children:[n.jsx("label",{children:"② 粘贴授权后浏览器跳转的完整回调地址"}),n.jsx("input",{value:T,placeholder:"https://platform.openai.com/auth/callback?code=...&state=...",onChange:ne=>b(ne.target.value),disabled:!E||G})]})]}),ae&&n.jsx("p",{className:"form-error",children:ae}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:r,disabled:G,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",onClick:le,disabled:!E||G,children:G?"处理中":"完成授权"})]})]})})}function Tp({limits:c}){const m=be(c).filter(y=>y.label||y.name).slice(0,3);return m.length?n.jsx("div",{className:"quota-bars",children:m.map(y=>{const r=Ep(y);return n.jsxs("div",{className:"quota-bar",children:[n.jsxs("div",{className:"quota-bar-label",children:[n.jsx("strong",{children:y.label||y.name}),n.jsx("span",{children:Mp(y,r)})]}),n.jsx("div",{className:"quota-bar-track",children:n.jsx("span",{style:{width:`${r}%`}})})]},`${y.label||y.name}-${y.resetAt||""}`)})}):null}function Ep(c){return typeof c.percentRemaining=="number"&&Number.isFinite(c.percentRemaining)?Math.max(0,Math.min(100,c.percentRemaining)):typeof c.remaining=="number"&&typeof c.limit=="number"&&c.limit>0?Math.max(0,Math.min(100,c.remaining/c.limit*100)):typeof c.used=="number"&&typeof c.limit=="number"&&c.limit>0?Math.max(0,Math.min(100,(c.limit-c.used)/c.limit*100)):0}function Mp(c,m){const y=c.resetAt?` · ${el(c.resetAt)}`:"";return typeof c.remaining=="number"?`${Math.round(m)}% 剩余${y}`:`${Math.round(m)}%${y}`}function zp(c){const m=be(c.models).join(" ").toLowerCase(),y=["对话"];c.streamMode!=="disabled"&&y.push("流式"),/(image|dall-e|gpt-image)/.test(m)&&y.push("图片"),(c.openaiAccountCount??c.openaiAccounts?.length??0)>0&&y.push("账号池");const r=c.upstreamKeyCount??0;return r>1&&y.push(`${r} Key 轮询`),y}function Op(c){if(c.status==="invalid"||c.credentialMode==="browser-session")return!0;if(!c.expiresAt)return!1;const m=new Date(c.expiresAt).getTime();return Number.isFinite(m)&&m-Date.now()<=1440*60*1e3}function _p({channels:c,groups:m,onUpdate:y,onCreate:r,onImport:E,onDelete:O,onSyncModels:K,onCheck:P}){const T=Aa("openai"),[b,G]=g.useState(!1),[_,ae]=g.useState(T.provider),[te,de]=g.useState(T.name),[le,ne]=g.useState(T.baseUrl),[ie,ge]=g.useState(T.models.join(", ")),[me,Ce]=g.useState(""),[F,ve]=g.useState(""),[D,ee]=g.useState(!1),[oe,Ne]=g.useState(!1);function Me(Q){const re=Aa(Q);ae(re.provider),de(re.name),ne(re.baseUrl),ge(re.models.join(", ")),ve("")}async function ue(Q){Q.preventDefault(),ee(!0),ve("");try{await r({name:te.trim()||Aa(_).name,provider:_,baseUrl:le.trim(),...xm(me),models:Ic(ie),streamMode:"auto"}),G(!1),Ce(""),Me(_)}catch(re){ve(re instanceof Error?re.message:"渠道创建失败")}finally{ee(!1)}}return n.jsxs(lt,{title:"渠道",children:[n.jsxs("div",{className:"channel-page-intro",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"管理上游服务"}),n.jsx("span",{children:"每个渠道对应一个 API 上游。先添加渠道,再检测连通性并同步可用模型。"})]}),n.jsxs("div",{className:"channel-page-summary",children:[n.jsxs("span",{children:[n.jsx("b",{children:c.length})," 个渠道"]}),n.jsxs("span",{children:[n.jsx("b",{children:c.filter(Q=>Q.status!=="disabled").length})," 个已启用"]})]})]}),n.jsxs("div",{className:"panel-toolbar channel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"列表显示当前状态;点击任一渠道可修改连接、模型和计费设置。"}),n.jsx("button",{className:"primary-button",onClick:()=>G(Q=>!Q),children:b?"取消新增":"+ 新增渠道"})]}),b&&n.jsxs("form",{className:"channel-card channel-create-form",onSubmit:ue,children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"选择渠道类型"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:Aa(_).label}),n.jsx("small",{children:"选择后自动填入建议配置"})]}),n.jsx("div",{role:"listbox","aria-label":"选择渠道类型",children:Fc.map(Q=>n.jsxs("button",{type:"button",className:_===Q.provider?"selected":"",onClick:re=>{Me(Q.provider),re.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:Q.label}),n.jsx("span",{children:"使用推荐的名称和地址"})]},Q.provider))})]})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:te,onChange:Q=>de(Q.target.value),placeholder:"例如 OpenAI 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:sl(_),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:le,onChange:Q=>ne(Q.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"上游 Key"}),n.jsx("textarea",{className:"channel-key-input",value:me,onChange:Q=>Ce(Q.target.value),placeholder:_==="codex"?"账号池导入后使用":_==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发",autoComplete:"off",rows:3})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsx("button",{type:"button",className:"model-pull-button",onClick:()=>{if(_!=="codex"&&!le.trim()){ve("请先填写 Base URL 再获取模型");return}ve(""),Ne(!0)},children:"从上游获取模型"})]}),n.jsx("textarea",{value:ie,onChange:Q=>ge(Q.target.value),placeholder:"多个模型用逗号分隔,或点上方『从上游获取模型』拉取后多选"})]})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("span",{className:"model-create-message",role:"status",children:F}),n.jsx("button",{className:"secondary-button",type:"button",onClick:()=>Me(_),disabled:D,children:"填入模板"}),n.jsx("button",{className:"primary-button",type:"submit",disabled:D,children:D?"创建中":"创建渠道"})]})]}),b&&oe&&n.jsx(jm,{subtitle:`${te.trim()||Aa(_).name} · 勾选需要接入的模型`,current:Ic(ie),loadModels:async()=>{const Q=await pe("/api/channel-model-preview",{method:"POST",body:JSON.stringify({provider:_,baseUrl:le.trim(),upstreamApiKey:me})});return be(Q.models)},onConfirm:async Q=>{ge(Q.join(", "))},onClose:()=>Ne(!1)}),n.jsxs("div",{className:"channels-stack",children:[c.map(Q=>n.jsx(Dp,{channel:Q,groups:m,onUpdate:y,onImport:E,onDelete:O,onSyncModels:K,onCheck:P},Q.id)),c.length===0&&n.jsx(Qt,{text:"暂无渠道,先在后端添加渠道接口或导入配置"})]})]})}function Dp({channel:c,groups:m,onUpdate:y,onImport:r,onDelete:E,onSyncModels:O,onCheck:K}){const[P,T]=g.useState(c.name),[b,G]=g.useState(c.provider),[_,ae]=g.useState(c.streamMode||"auto"),[te,de]=g.useState(c.baseUrl),[le,ne]=g.useState(be(c.allowedGroupIds)),[ie,ge]=g.useState(be(c.models).join(", ")),[me,Ce]=g.useState("saved"),[F,ve]=g.useState(String(c.inputPricePer1K||0)),[D,ee]=g.useState(String(c.outputPricePer1K||0)),[oe,Ne]=g.useState(!!c.webEndpoint),[Me,ue]=g.useState(""),[Q,re]=g.useState(""),[V,A]=g.useState(!1),Y=c.openaiAccountCount??c.openaiAccounts?.length??0,p=be(c.models).length,z=zp(c),$=c.status==="disabled",f={saved:"已保存",template:"模板",manual:"手动",synced:"上游同步"}[me],N=Ns.find(J=>J.value===_)||Ns[0],q={auto:"自动处理(推荐)",real:"强制流式",fake:"兼容流式",disabled:"关闭流式"};g.useEffect(()=>{T(c.name),G(c.provider),ae(c.streamMode||"auto"),de(c.baseUrl),ne(be(c.allowedGroupIds)),ge(be(c.models).join(", ")),Ce("saved"),ve(String(c.inputPricePer1K||0)),ee(String(c.outputPricePer1K||0)),Ne(!!c.webEndpoint),ue("")},[c.id,c.name,c.provider,c.streamMode,c.baseUrl,c.models,c.inputPricePer1K,c.outputPricePer1K,c.webEndpoint]);async function L(){const J=Z();re("save");try{await y(c.id,J),ue("")}finally{re("")}}function Z(){const J=Es(b),Je=!/^https?:\/\//i.test(te.trim())&&J?J:te,ut={name:P.trim()||c.name,provider:b,streamMode:_,baseUrl:Je,inputPricePer1K:Number(F)||0,outputPricePer1K:Number(D)||0,webEndpoint:oe,models:ie.split(",").map(Ie=>Ie.trim()).filter(Boolean),allowedGroupIds:le};return Object.assign(ut,xm(Me)),ut}async function xe(){const J=c.status==="disabled"?"healthy":"disabled";re("status");try{await y(c.id,{...Z(),status:J}),ue("")}finally{re("")}}async function M(){re("sync");try{await y(c.id,Z()),ue(""),A(!0)}finally{re("")}}function je(){const J=Aa(b);ge(J.models.join(", ")),Ce("template"),J.baseUrl&&!/^https?:\/\//i.test(te.trim())&&de(J.baseUrl)}async function Se(){re("check");try{await L(),await K(c.id)}finally{re("")}}async function ot(J){re("import");try{await r(c.id,J)}finally{re("")}}return n.jsxs(n.Fragment,{children:[n.jsxs("details",{className:"channel-card channel-card-collapsible",children:[n.jsxs("summary",{className:"channel-card-head channel-list-row",children:[n.jsxs("div",{className:"channel-identity",children:[n.jsx("strong",{children:c.name}),n.jsx("span",{children:sl(b)}),n.jsx("small",{children:c.baseUrl||"尚未配置上游地址"}),n.jsx("div",{className:"channel-capability-tags",children:z.map(J=>n.jsx("span",{children:J},J))})]}),n.jsxs("div",{className:"channel-list-meta",children:[n.jsxs("span",{children:[n.jsx("b",{children:p})," 个模型"]}),Y>0&&n.jsxs("span",{children:[n.jsx("b",{children:Y})," 个账号"]})]}),n.jsxs("div",{className:"channel-check-result",children:[n.jsx("span",{children:"连通性"}),n.jsx("b",{className:c.lastError?"is-error":c.lastCheckedAt?"is-ok":"",children:c.lastError?"检测失败":c.lastCheckedAt?`已检测 ${el(c.lastCheckedAt)}`:"尚未检测"})]}),n.jsxs("div",{className:"channel-list-status",children:[n.jsx(Dt,{tone:c.status,children:$?"已停用":_t(c.status)}),n.jsx("span",{className:"channel-expand-hint",children:"配置"})]})]}),n.jsxs("div",{className:"channel-editor-controls",children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"供应商"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:sl(b)}),n.jsx("small",{children:"修改上游协议类型"})]}),n.jsx("div",{role:"listbox","aria-label":"供应商",children:eo.map(J=>n.jsxs("button",{type:"button",className:b===J.value?"selected":"",onClick:Je=>{G(J.value);const ut=Es(J.value);ut&&!/^https?:\/\//i.test(te.trim())&&de(ut),Je.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:J.label}),n.jsx("span",{children:J.value==="compatible"?"适用于兼容 OpenAI 格式的服务":"选择对应的上游协议"})]},J.value))})]})]}),n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"响应方式"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:q[N.value]}),n.jsx("small",{children:N.description})]}),n.jsx("div",{role:"listbox","aria-label":"响应方式",children:Ns.map(J=>n.jsxs("button",{type:"button",className:_===J.value?"selected":"",onClick:Je=>{ae(J.value),Je.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:q[J.value]}),n.jsx("span",{children:J.description})]},J.value))})]})]})]}),(b==="codex"||Y>0)&&n.jsxs("div",{className:"setting",children:[n.jsxs("div",{children:[n.jsx("span",{children:"网页对话接口"}),n.jsx("small",{children:"开启后走 ChatGPT 网页对话接口,把 Plus 订阅账号包装成 API"})]}),n.jsx("div",{className:"setting-value",children:n.jsx("button",{type:"button",className:oe?"ios-switch is-on":"ios-switch","aria-label":oe?"关闭网页对话接口":"开启网页对话接口","aria-pressed":oe,onClick:()=>Ne(J=>!J),children:n.jsx("span",{})})})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:P,onChange:J=>T(J.target.value),placeholder:"例如 Gemini 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:sl(b),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:te,onChange:J=>de(J.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"优先级"}),n.jsx("input",{value:c.priority,readOnly:!0})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsxs("small",{children:["来源:",f]})]}),n.jsx("textarea",{value:ie,onChange:J=>{ge(J.target.value),Ce("manual")},placeholder:"优先拉取上游模型,也可以手动补充,多个用逗号分隔"}),n.jsxs("div",{className:"channel-model-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:je,disabled:Q!=="",children:"填入模板"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:M,disabled:Q!=="",children:Q==="sync"?"拉取中":"获取上游模型"})]})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsxs("span",{children:["上游 Key",(c.upstreamKeyCount??0)>0?` (已配置 ${c.upstreamKeyCount} 个)`:c.upstreamKeySet?" (已配置)":""]}),n.jsx("textarea",{className:"channel-key-input",value:Me,onChange:J=>ue(J.target.value),placeholder:b==="codex"?"Codex 账号池不需要上游 Key":b==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发;留空不修改",autoComplete:"off",rows:3})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输入单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:F,onChange:J=>ve(J.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输出单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:D,onChange:J=>ee(J.target.value)})]}),n.jsx("span",{className:"channel-billing-note",children:"定价可先留空;接入是否可用优先看渠道检测和模型同步结果。"})]}),n.jsxs("div",{className:"channel-group-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"可见分组"}),n.jsx("small",{children:le.length?`已选择 ${le.length} 个分组`:"全部用户可用"})]}),m.length===0?n.jsx("p",{className:"channel-group-empty",children:"还没有用户分组。去「分组」页创建后,可在这里把渠道限制为只对特定分组开放。"}):n.jsx("div",{className:"channel-group-options",children:m.map(J=>{const Je=le.includes(J.id);return n.jsxs("button",{type:"button",className:Je?"selected":"","aria-pressed":Je,onClick:()=>ne(ut=>Je?ut.filter(Ie=>Ie!==J.id):[...ut,J.id]),children:[n.jsx("span",{children:J.name}),J.description&&n.jsx("small",{children:J.description})]},J.id)})})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("button",{className:"secondary-button",onClick:Se,disabled:Q!=="",children:Q==="check"?"检测中":"检测渠道"}),n.jsx("button",{className:"primary-button",onClick:L,disabled:Q!=="",children:Q==="save"?"保存中":"保存"}),n.jsxs("details",{className:"channel-more-actions",children:[n.jsx("summary",{children:"更多操作"}),n.jsxs("div",{children:[n.jsxs("label",{className:"secondary-button",children:[Q==="import"?"导入中":"导入账号 JSON",n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:Q!=="",onChange:J=>{const Je=J.target.files?.[0];Je&&ot(Je),J.target.value=""}})]}),n.jsx("button",{className:"secondary-button",onClick:xe,disabled:Q!=="",children:c.status==="disabled"?"启用渠道":"停用渠道"}),n.jsx("button",{className:"danger-button",onClick:()=>E(c.id),disabled:Q!=="",children:"删除渠道"})]})]})]})]}),V&&n.jsx(jm,{subtitle:`${c.name} · 勾选需要接入的模型`,current:ie.split(",").map(J=>J.trim()).filter(Boolean),loadModels:async()=>{const J=await pe(`/api/channels/${c.id}/upstream-models`,{method:"POST",body:JSON.stringify({})});return be(J.models)},onConfirm:async J=>{await O(c.id,J)},onClose:()=>A(!1)})]})}function jm({subtitle:c,current:m,loadModels:y,onConfirm:r,onClose:E}){const[O,K]=g.useState(!0),[P,T]=g.useState(""),[b,G]=g.useState([]),[_,ae]=g.useState(new Set),[te,de]=g.useState(""),[le,ne]=g.useState(!1);g.useEffect(()=>{let D=!1;return(async()=>{K(!0),T("");try{const ee=await y();if(D)return;const oe=new Set,Ne=be(ee).map(ue=>ue.trim()).filter(ue=>{if(!ue)return!1;const Q=ue.toLowerCase();return oe.has(Q)?!1:(oe.add(Q),!0)}),Me=new Set(m.map(ue=>ue.toLowerCase()));G(Ne),ae(new Set(Ne.filter(ue=>Me.has(ue.toLowerCase()))))}catch(ee){D||T(ee instanceof Error?ee.message:"获取上游模型失败")}finally{D||K(!1)}})(),()=>{D=!0}},[]);const ie=te.trim().toLowerCase(),ge=ie?b.filter(D=>D.toLowerCase().includes(ie)):b,me=ge.length>0&&ge.every(D=>_.has(D));function Ce(D){ae(ee=>{const oe=new Set(ee);return oe.has(D)?oe.delete(D):oe.add(D),oe})}function F(){ae(D=>{const ee=new Set(D);return me?ge.forEach(oe=>ee.delete(oe)):ge.forEach(oe=>ee.add(oe)),ee})}async function ve(){const D=new Set(b.map(ue=>ue.toLowerCase())),ee=m.filter(ue=>!D.has(ue.toLowerCase())),oe=b.filter(ue=>_.has(ue)),Ne=new Set,Me=[...ee,...oe].filter(ue=>{const Q=ue.toLowerCase();return Ne.has(Q)?!1:(Ne.add(Q),!0)});ne(!0);try{await r(Me),E()}catch{ne(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:E,children:n.jsxs("div",{className:"modal-card model-picker-modal",onClick:D=>D.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"选择上游模型"}),n.jsx("span",{children:c})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:E,children:"×"})]}),O?n.jsx("div",{className:"model-picker-status",children:"正在获取上游模型…"}):P?n.jsx("div",{className:"model-picker-status model-picker-error",children:P}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"model-picker-toolbar",children:[n.jsx("input",{className:"model-picker-search",value:te,onChange:D=>de(D.target.value),placeholder:"搜索模型名称",autoFocus:!0}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:F,disabled:ge.length===0,children:me?"取消全选":"全选"})]}),n.jsxs("div",{className:"model-picker-count",children:["共 ",b.length," 个 · 已选 ",_.size," 个",ie?` · 匹配 ${ge.length} 个`:""]}),n.jsxs("div",{className:"model-picker-list",children:[ge.map(D=>{const ee=_.has(D),oe=m.some(Ne=>Ne.toLowerCase()===D.toLowerCase());return n.jsxs("label",{className:`model-picker-row${ee?" checked":""}`,children:[n.jsx("input",{type:"checkbox",checked:ee,onChange:()=>Ce(D)}),n.jsx("span",{className:"model-picker-name",children:D}),oe&&n.jsx("span",{className:"model-picker-tag",children:"已接入"})]},D)}),ge.length===0&&n.jsx("div",{className:"model-picker-status",children:"没有匹配的模型"})]})]}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:E,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:O||!!P||le,onClick:ve,children:le?"保存中":`导入所选 (${_.size})`})]})]})})}function Up({logs:c,onCopy:m}){const[y,r]=g.useState(c),[E,O]=g.useState(c.length),[K,P]=g.useState(1),[T,b]=g.useState(""),[G,_]=g.useState("all"),[ae,te]=g.useState(null),[de,le]=g.useState(!1),[ne,ie]=g.useState(!1),ge=25,me=Math.max(1,Math.ceil(E/ge));g.useEffect(()=>{P(1)},[T,G]),g.useEffect(()=>{K>me&&P(me)},[K,me]),g.useEffect(()=>{const F=new AbortController,ve=window.setTimeout(async()=>{le(!0);try{const D=new URLSearchParams({page:String(K),pageSize:String(ge),status:G,q:T.trim()}),ee=await pe(`/api/logs?${D}`,{signal:F.signal}),oe=be(ee.logs);r(oe),O(ee.total||0),te(Ne=>Ne&&oe.some(Me=>Me.id===Ne.id)?Ne:null)}catch(D){D instanceof DOMException&&D.name==="AbortError"||(r([]),O(0))}finally{F.signal.aborted||le(!1)}},T?250:0);return()=>{window.clearTimeout(ve),F.abort()}},[K,T,G]);async function Ce(F){if(ae?.id===F.id){te(null);return}te(F),ie(!0);try{const ve=await pe(`/api/logs/${encodeURIComponent(F.id)}`);te(ve.log)}catch{te(F)}finally{ie(!1)}}return n.jsxs(lt,{title:"调用日志",children:[n.jsxs("div",{className:"logs-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Ot,{name:"search"}),n.jsx("input",{value:T,onChange:F=>b(F.target.value),placeholder:"搜索请求 ID、用户、Key、模型、渠道或错误码"})]}),n.jsx("div",{className:"log-status-filter",role:"group","aria-label":"日志状态筛选",children:[{value:"all",label:"全部"},{value:"success",label:"成功"},{value:"failed",label:"失败"}].map(F=>n.jsx("button",{type:"button",className:G===F.value?"selected":"",onClick:()=>_(F.value),children:F.label},F.value))}),n.jsx("span",{className:"muted-inline",children:de?"加载中":`共 ${E} 条`})]}),n.jsxs("div",{className:ae?"logs-layout has-detail":"logs-layout",children:[n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head logs-table",children:[n.jsx("span",{children:"请求"}),n.jsx("span",{children:"模型"}),n.jsx("span",{children:"渠道"}),n.jsx("span",{children:"状态"})]}),y.map(F=>n.jsx("div",{className:"log-entry",children:n.jsxs("div",{className:ae?.id===F.id?"table-row logs-table selected":"table-row logs-table",role:"button",tabIndex:0,onClick:()=>Ce(F),onKeyDown:ve=>{(ve.key==="Enter"||ve.key===" ")&&Ce(F)},children:[n.jsxs("span",{children:[n.jsx("strong",{children:to(F)}),n.jsxs("small",{children:[F.id," · ",el(F.createdAt)," · ",F.latencyMs,"ms"]})]}),n.jsx("span",{children:ap(F)}),n.jsx("span",{children:np(F)}),n.jsx(Dt,{tone:F.status,children:_t(F.status)})]})},F.id)),!de&&y.length===0&&n.jsx(Qt,{text:T||G!=="all"?"没有匹配的日志":"暂无调用日志"})]}),ae&&n.jsx(Rp,{log:ae,loading:ne,onCopy:m})]}),me>1&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:K<=1||de,onClick:()=>P(F=>Math.max(1,F-1)),children:"上一页"}),n.jsxs("span",{children:[K," / ",me]}),n.jsx("button",{className:"secondary-button",disabled:K>=me||de,onClick:()=>P(F=>Math.min(me,F+1)),children:"下一页"})]})]})}function Rp({log:c,loading:m,onCopy:y}){if(!c)return n.jsx("aside",{className:"log-inspector empty-inspector",children:n.jsx("span",{children:"选择一条日志查看详情"})});const r=Number(c.inputTokens||0),E=Number(c.outputTokens||0),O=typeof c.attempts=="number"?Math.max(0,c.attempts):null,K=[["请求 ID",c.id],["状态",_t(c.status)],["时间",lp(c.createdAt)],["用户 ID",c.userId||"未识别"],["API Key",c.apiKeyPrefix?`${c.apiKeyPrefix}***`:"未识别"],["模型",c.model||"未提供"],["渠道",c.channel||"未选择"],["实际账号",c.account||"未记录"],["响应耗时",`${c.latencyMs} ms`],["尝试次数",O===null?"未记录":String(O)],["是否重试",O===null?"未记录":O>1?"是":"否"],["输入 Tokens",Ca(r)],["输出 Tokens",Ca(E)],["总 Tokens",Ca(r+E)],["扣费",c.cost.toFixed(4)],["错误码",c.errorCode||"无"]];return n.jsxs("aside",{className:"log-inspector",children:[n.jsxs("header",{children:[n.jsxs("div",{children:[n.jsx("span",{children:m?"加载中":"日志详情"}),n.jsx("strong",{children:to(c)})]}),n.jsx(Dt,{tone:c.status,children:_t(c.status)})]}),n.jsx("div",{className:"log-detail",children:K.map(([P,T])=>n.jsxs("div",{children:[n.jsx("span",{children:P}),n.jsx("strong",{title:T,children:T})]},P))}),n.jsxs("div",{className:"log-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>y(c.id,"请求 ID 已复制"),children:"复制请求 ID"}),c.errorCode&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>y(c.errorCode||"","错误码已复制"),children:"复制错误码"})]})]})}function Hp({models:c,channels:m,groups:y}){const[r,E]=g.useState(null),[O,K]=g.useState(null),[P,T]=g.useState("username"),[b,G]=g.useState("0"),[_,ae]=g.useState(""),[te,de]=g.useState({enabled:!0,minReward:.1,maxReward:1}),[le,ne]=g.useState({logRetentionDays:30,maxLogs:1e4,maxQuotaEntries:2e4}),[ie,ge]=g.useState(null),[me,Ce]=g.useState(null),[F,ve]=g.useState(""),[D,ee]=g.useState(""),[oe,Ne]=g.useState(""),[Me,ue]=g.useState(""),[Q,re]=g.useState(""),[V,A]=g.useState(""),[Y,p]=g.useState(""),[z,$]=g.useState(""),[f,N]=g.useState(""),[q,L]=g.useState(!1),[Z,xe]=g.useState("system"),M=c.find(R=>R.recommended&&R.status==="available")?.id||c.find(R=>R.status==="available")?.id||"未配置",je=m.filter(R=>R.status!=="disabled").length,Se=[{value:"system",label:"系统",description:"运行概况"},{value:"cli",label:"CLI 接入",description:"一键配置"},{value:"auth",label:"注册",description:"开放方式"},{value:"check-in",label:"签到",description:"奖励范围"},{value:"admin",label:"管理员",description:"账号绑定"},{value:"discord",label:"Discord",description:"登录限制"},{value:"maintenance",label:"维护",description:"日志保留"},{value:"backup",label:"备份",description:"导出恢复"}],ot=Se.find(R=>R.value===Z)||Se[0];g.useEffect(()=>{Promise.all([pe("/api/settings/discord"),pe("/api/settings/auth"),pe("/api/settings/check-in"),pe("/api/account/me"),pe("/api/settings/maintenance"),pe("/api/health")]).then(([R,Ue,rt,jt,ht,Pe])=>{E(Wc(R.discord)),$(be(R.discord.blockedGuildIds).join(` +`)),K(Ue.auth.registrationEnabled),T(Ms(Ue.auth.registrationMode)),G(String(Ue.auth.defaultBalance||0)),ae(Ue.auth.defaultGroupId||""),de(rt.checkIn),Ce(jt.account),ve(jt.account?.username||""),ee(jt.user.name||""),Ne(jt.account?.email||""),ue(jt.account?.discordUserId||""),ne(ht.maintenance),ge(Pe)}).catch(()=>N("设置加载失败"))},[]);async function J(R=O,Ue=P,rt=Number(b),jt=_){if(R!==null)try{const ht=await pe("/api/settings/auth",{method:"PATCH",body:JSON.stringify({registrationEnabled:R,registrationMode:Ue,defaultBalance:rt,defaultGroupId:jt})});K(ht.auth.registrationEnabled),T(Ms(ht.auth.registrationMode)),G(String(ht.auth.defaultBalance||0)),ae(ht.auth.defaultGroupId||""),N(ht.auth.registrationEnabled?"注册设置已保存":"已关闭用户注册")}catch(ht){N(ht instanceof Error?ht.message:"注册设置保存失败")}}async function Je(){O!==null&&J(!O,P)}async function ut(){L(!0),N("");try{const R=await pe("/api/settings/check-in",{method:"PATCH",body:JSON.stringify(te)});de(R.checkIn),N(R.checkIn.enabled?"签到奖励设置已保存":"已关闭每日签到")}catch(R){N(R instanceof Error?R.message:"签到设置保存失败")}finally{L(!1)}}async function Ie(){if(r){L(!0),N("");try{const R=Wc(r),Ue=z.split(/[\s,]+/).map(jt=>jt.trim()).filter(Boolean),rt=await pe("/api/settings/discord",{method:"PATCH",body:JSON.stringify({...R,blockedGuildIds:Ue,clientSecret:Y})});E(Wc(rt.discord)),$(be(rt.discord.blockedGuildIds).join(` +`)),p(""),N("Discord 配置已保存")}catch(R){N(R instanceof Error?R.message:"保存失败,请检查填写内容")}finally{L(!1)}}}async function tl(){try{const R=await pe("/api/account/profile",{method:"PATCH",body:JSON.stringify({username:F,displayName:D,email:oe,discordUserId:Me,currentPassword:Q,newPassword:V})});Ce(R.account),ve(R.account.username),Ne(R.account.email||""),ue(R.account.discordUserId||""),re(""),A(""),N("管理员账号已保存")}catch(R){N(R instanceof Error?R.message:"账号设置保存失败")}}async function k(){L(!0),N("");try{const R=await pe("/api/settings/maintenance",{method:"PATCH",body:JSON.stringify(le)});ne(R.maintenance),N("维护设置已保存,历史数据已按新规则清理")}catch(R){N(R instanceof Error?R.message:"维护设置保存失败")}finally{L(!1)}}async function mt(){L(!0),N("");try{const R=await fetch("/api/backup",{credentials:"include"});if(!R.ok)throw new Error("备份导出失败");const Ue=await R.blob(),jt=(R.headers.get("Content-Disposition")||"").match(/filename="([^"]+)"/)?.[1]||"capi-backup.json",ht=URL.createObjectURL(Ue),Pe=document.createElement("a");Pe.href=ht,Pe.download=jt,Pe.click(),URL.revokeObjectURL(ht),N("备份已导出,请妥善保管")}catch(R){N(R instanceof Error?R.message:"备份导出失败")}finally{L(!1)}}async function Ut(R){if(window.confirm("恢复会覆盖当前全部数据,并退出现有登录会话。确定继续?")){L(!0),N("");try{const Ue=await fetch("/api/restore",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:R}),rt=await Ue.json().catch(()=>null);if(!Ue.ok)throw new Error(rt?.error?.message||"备份恢复失败");N(`已恢复 ${rt.users} 个用户、${rt.channels} 条渠道和 ${rt.models} 个模型,请重新登录`)}catch(Ue){N(Ue instanceof Error?Ue.message:"备份恢复失败")}finally{L(!1)}}}return n.jsxs("div",{className:"settings-layout",children:[n.jsx("div",{className:"settings-tabs",children:Se.map(R=>n.jsxs("button",{type:"button",className:Z===R.value?"selected":"",onClick:()=>xe(R.value),children:[n.jsx("strong",{children:R.label}),n.jsx("small",{children:R.description})]},R.value))}),n.jsxs("div",{className:"settings-tab-note",children:[n.jsx("strong",{children:ot.label}),n.jsx("span",{children:ot.description})]}),Z==="system"&&n.jsx(lt,{title:"系统设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsx(Pt,{label:"接口兼容",value:"OpenAI API"}),n.jsx(Pt,{label:"当前默认模型",value:M}),n.jsx(Pt,{label:"已配置渠道",value:`${m.length} 个,${je} 个启用`}),n.jsx(Pt,{label:"可选供应商",value:`${eo.length} 种`}),n.jsx(Pt,{label:"运行版本",value:`${ie?.version||"未知"} · ${ie?.commit||"未知"}`}),n.jsx(Pt,{label:"构建时间",value:ie?.buildTime?el(ie.buildTime):"本地构建"}),n.jsx(Pt,{label:"账号自动检测",value:"每 15 分钟自动检测一次"})]})}),Z==="cli"&&n.jsxs(lt,{title:"CLI 工具接入",children:[n.jsx("p",{className:"cli-intro",children:"CAPI 兼容 OpenAI 和 Anthropic 协议,常见 AI 命令行工具可直接接入。"}),n.jsxs("div",{className:"cli-credentials",children:[n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"Base URL"}),n.jsx("code",{children:_l()}),n.jsx("button",{type:"button",className:"copy-button","aria-label":"复制",onClick:()=>{As(_l()),N("已复制 Base URL")},children:n.jsx(Ot,{name:"copy"})})]}),n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"API Key"}),n.jsx("code",{children:"cat_你的_api_key"})]})]}),n.jsxs("div",{className:"cli-tools",children:[n.jsxs("details",{className:"cli-tool",open:!0,children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Claude Code"}),n.jsx("span",{children:"Anthropic Messages 协议"})]}),n.jsx("pre",{children:`export ANTHROPIC_BASE_URL="${_l()}" +export ANTHROPIC_AUTH_TOKEN="cat_你的_api_key" +export ANTHROPIC_MODEL="${M}" +claude`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Codex CLI"}),n.jsx("span",{children:"OpenAI Chat 协议"})]}),n.jsxs("p",{children:["编辑 ",n.jsx("code",{children:"~/.codex/config.toml"}),":"]}),n.jsx("pre",{children:`model = "${M}" +model_provider = "capi" + +[model_providers.capi] +name = "CAPI" +base_url = "${_l()}/v1" +env_key = "CAPI_KEY" +wire_api = "chat"`}),n.jsx("p",{children:"然后设置环境变量并运行:"}),n.jsx("pre",{children:`export CAPI_KEY="cat_你的_api_key" +codex`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Aider"}),n.jsx("span",{children:"OpenAI 兼容"})]}),n.jsx("pre",{children:`export OPENAI_API_BASE="${_l()}" +export OPENAI_API_KEY="cat_你的_api_key" +aider --model openai/${M}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Cline / Roo Code / Kilo Code"}),n.jsx("span",{children:"VS Code 插件"})]}),n.jsxs("p",{children:["在插件设置中选择 ",n.jsx("strong",{children:"OpenAI Compatible"}),":"]}),n.jsx("pre",{children:`Base URL: ${_l()}/v1 +API Key: cat_你的_api_key +Model ID: ${M}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"通用 OpenAI SDK"}),n.jsx("span",{children:"Python / Node.js"})]}),n.jsx("pre",{children:`export OPENAI_BASE_URL="${_l()}" +export OPENAI_API_KEY="cat_你的_api_key"`}),n.jsx("pre",{children:`from openai import OpenAI +client = OpenAI() +response = client.chat.completions.create( + model="${M}", + messages=[{"role": "user", "content": "hello"}] +)`})]})]}),f&&n.jsx("p",{className:"cli-message",role:"status",children:f})]}),Z==="maintenance"&&n.jsx(lt,{title:"维护设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志保留天数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"1",max:"3650",value:le.logRetentionDays,onChange:R=>ne(Ue=>({...Ue,logRetentionDays:Number(R.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"1000000",step:"100",value:le.maxLogs,onChange:R=>ne(Ue=>({...Ue,maxLogs:Number(R.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"额度流水最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"2000000",step:"100",value:le.maxQuotaEntries,onChange:R=>ne(Ue=>({...Ue,maxQuotaEntries:Number(R.target.value)}))})})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:f}),n.jsx("button",{type:"button",className:"primary-button",disabled:q,onClick:k,children:q?"保存中":"保存维护设置"})]})]})}),Z==="backup"&&n.jsx(lt,{title:"备份与恢复",children:n.jsx("div",{className:"settings-group",children:n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["备份与恢复",n.jsx("small",{children:"包含账号哈希和加密后的上游密钥,恢复时需要相同的 SECRET_KEY"})]}),n.jsxs("div",{className:"setting-value backup-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",disabled:q,onClick:mt,children:"导出备份"}),n.jsxs("label",{className:"secondary-button",children:["恢复备份",n.jsx("input",{type:"file",accept:"application/json,.json",disabled:q,onChange:R=>{const Ue=R.target.files?.[0];Ue&&Ut(Ue),R.target.value=""}})]})]})]})})}),Z==="auth"&&n.jsx(lt,{title:"账号与注册",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放用户注册"}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:O?"启用":"关闭"}),n.jsx("button",{type:"button",className:O?"ios-switch is-on":"ios-switch","aria-label":O?"关闭用户注册":"开放用户注册","aria-pressed":!!O,onClick:Je,children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"注册方式"}),n.jsx("div",{className:"registration-mode-control",role:"group","aria-label":"注册方式",children:[{value:"username",label:"账号密码"},{value:"email",label:"邮箱"},{value:"discord",label:"Discord"}].map(R=>n.jsx("button",{type:"button",className:P===R.value?"selected":"",onClick:()=>J(O??!0,R.value),children:R.label},R.value))})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["新用户初始额度",n.jsx("small",{children:"注册完成后自动发放,仅影响之后的新用户"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsx("input",{type:"number",min:"0",step:"0.01",value:b,onChange:R=>G(R.target.value),"aria-label":"新用户初始额度"}),n.jsx("button",{type:"button",className:"secondary-button",onClick:()=>J(O,P,Number(b)),children:"保存"})]})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["默认注册分组",n.jsx("small",{children:"新注册用户自动归入该分组,决定他们能用哪些渠道"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsxs("select",{value:_,onChange:R=>ae(R.target.value),"aria-label":"默认注册分组",children:[y.map(R=>n.jsx("option",{value:R.id,children:R.name},R.id)),y.length===0&&n.jsx("option",{value:"",children:"暂无分组"})]}),n.jsx("button",{type:"button",className:"secondary-button",disabled:y.length===0,onClick:()=>J(O,P,Number(b),_),children:"保存"})]})]})]})}),Z==="check-in"&&n.jsx(lt,{title:"每日签到奖励",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["开放每日签到",n.jsx("small",{children:"用户每天可领取一次随机额度,按北京时间刷新"})]}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:te.enabled?"启用":"关闭"}),n.jsx("button",{type:"button",className:te.enabled?"ios-switch is-on":"ios-switch","aria-label":te.enabled?"关闭每日签到":"开放每日签到","aria-pressed":te.enabled,onClick:()=>de(R=>({...R,enabled:!R.enabled})),children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting check-in-settings-row",children:[n.jsxs("span",{children:["随机奖励范围",n.jsx("small",{children:"领取金额精确到 0.01,直接计入用户余额和额度流水"})]}),n.jsxs("div",{className:"check-in-reward-inputs",children:[n.jsxs("label",{children:[n.jsx("span",{children:"最低"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:te.minReward,onChange:R=>de(Ue=>({...Ue,minReward:Number(R.target.value)}))})]}),n.jsxs("label",{children:[n.jsx("span",{children:"最高"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:te.maxReward,onChange:R=>de(Ue=>({...Ue,maxReward:Number(R.target.value)}))})]})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:f}),n.jsx("button",{type:"button",className:"primary-button",disabled:q,onClick:ut,children:q?"保存中":"保存签到设置"})]})]})}),Z==="admin"&&n.jsx(lt,{title:"管理员账号",children:n.jsxs("form",{className:"discord-settings",onSubmit:R=>{R.preventDefault(),tl()},children:[n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"登录账号"}),n.jsx("input",{value:F,onChange:R=>ve(R.target.value),autoComplete:"username"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:D,onChange:R=>ee(R.target.value),autoComplete:"name"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"邮箱"}),n.jsx("input",{type:"email",value:oe,onChange:R=>Ne(R.target.value),autoComplete:"email"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:Me,onChange:R=>ue(R.target.value),placeholder:me?.discordUserId?"已绑定":"输入管理员的 Discord 用户 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"当前密码"}),n.jsx("input",{type:"password",value:Q,onChange:R=>re(R.target.value),autoComplete:"current-password",placeholder:"修改密码时填写"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新密码"}),n.jsx("input",{type:"password",value:V,onChange:R=>A(R.target.value),autoComplete:"new-password",placeholder:"留空表示不修改"})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:f}),n.jsx("button",{className:"primary-button",type:"submit",children:"保存账号"})]})]})}),Z==="discord"&&n.jsx(lt,{title:"Discord 登录",children:r?n.jsxs("form",{className:"discord-settings",autoComplete:"off",onSubmit:R=>{R.preventDefault(),Ie()},children:[n.jsxs("div",{className:"discord-toggle-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"Discord 登录"}),n.jsx("span",{children:r.enabled?"已启用":"未启用"})]}),n.jsx("button",{type:"button",className:r.enabled?"ios-switch is-on":"ios-switch","aria-label":r.enabled?"停用 Discord 登录":"启用 Discord 登录","aria-pressed":r.enabled,onClick:()=>E({...r,enabled:!r.enabled}),children:n.jsx("span",{})})]}),n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"Client ID"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:r.clientId,onChange:R=>E({...r,clientId:R.target.value}),placeholder:"100000000000000001"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Client Secret"}),n.jsx("input",{type:"password",autoComplete:"new-password",value:Y,onChange:R=>p(R.target.value),placeholder:r.clientSecretSet?"已设置,留空表示不修改":"粘贴 Discord Client Secret"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"回调地址"}),n.jsx("input",{type:"url",value:r.redirectUri,onChange:R=>E({...r,redirectUri:R.target.value}),placeholder:"https://你的域名/api/auth/discord/callback"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"服务器 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedGuildId,onChange:R=>E({...r,allowedGuildId:R.target.value}),placeholder:"允许登录的服务器 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"身份组 ID"}),n.jsx("input",{inputMode:"numeric",value:r.allowedRoleId,onChange:R=>E({...r,allowedRoleId:R.target.value}),placeholder:"允许登录的身份组 ID"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"拉黑服务器 ID"}),n.jsx("textarea",{value:z,onChange:R=>$(R.target.value),placeholder:"每行一个服务器 ID;命中的用户禁止注册 / 登录",rows:3}),n.jsx("small",{children:"用户若加入了这些 Discord 服务器中的任意一个,将无法注册或登录(优先于上面的允许规则)。"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"登录成功跳转地址"}),n.jsx("input",{type:"url",value:r.authSuccessUrl,onChange:R=>E({...r,authSuccessUrl:R.target.value}),placeholder:"https://你的域名/"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"登录有效期(小时)"}),n.jsx("input",{type:"number",min:"1",max:"8760",value:r.sessionTtlHours,onChange:R=>E({...r,sessionTtlHours:Number(R.target.value)})})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:f}),n.jsx("button",{className:"primary-button",type:"submit",disabled:q,children:q?"保存中":"保存配置"})]})]}):n.jsx("div",{className:"empty",children:"正在读取配置"})})]})}function ul({label:c,value:m}){return n.jsxs("div",{className:"metric",children:[n.jsx("span",{children:c}),n.jsx("strong",{children:m})]})}function wp({groups:c,onCreate:m,onUpdate:y,onDelete:r}){const[E,O]=g.useState(""),[K,P]=g.useState(""),[T,b]=g.useState(!1);async function G(_){if(_.preventDefault(),!!E.trim()){b(!0);try{await m({name:E.trim(),description:K.trim()}),O(""),P("")}finally{b(!1)}}}return n.jsxs("section",{className:"models-page",children:[n.jsxs(lt,{title:"用户分组",children:[n.jsxs("form",{className:"channel-create-form",onSubmit:G,children:[n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"分组名称"}),n.jsx("input",{value:E,onChange:_=>O(_.target.value),placeholder:"例如 尊享用户 / 试用用户"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"说明"}),n.jsx("input",{value:K,onChange:_=>P(_.target.value),placeholder:"可选"})]})]}),n.jsx("div",{className:"channel-card-actions",children:n.jsx("button",{className:"primary-button",type:"submit",disabled:T||!E.trim(),children:T?"创建中":"创建分组"})})]}),n.jsx("p",{className:"muted-inline",children:"分组用于控制渠道对用户的可见范围:把用户归入分组,并在渠道上勾选「可见分组」即可限制访问。未分组的用户只能使用未限制分组的渠道。"})]}),n.jsx(lt,{title:"全部分组",children:c.length===0?n.jsx(Qt,{text:"还没有分组"}):n.jsx("div",{className:"channels-stack",children:c.map(_=>n.jsx(Bp,{group:_,onUpdate:y,onDelete:r},_.id))})})]})}function Bp({group:c,onUpdate:m,onDelete:y}){const[r,E]=g.useState(!1),[O,K]=g.useState(c.name),[P,T]=g.useState(c.description),[b,G]=g.useState(!1);async function _(){G(!0);try{await m(c.id,{name:O.trim(),description:P.trim()}),E(!1)}finally{G(!1)}}return n.jsx("div",{className:"channel-card",children:n.jsxs("div",{className:"channel-card-head",children:[n.jsx("div",{children:r?n.jsxs("div",{className:"group-edit-fields",children:[n.jsx("input",{value:O,onChange:ae=>K(ae.target.value),placeholder:"分组名称"}),n.jsx("input",{value:P,onChange:ae=>T(ae.target.value),placeholder:"说明"})]}):n.jsxs(n.Fragment,{children:[n.jsx("strong",{children:c.name}),c.description&&n.jsx("span",{children:c.description}),n.jsxs("small",{children:["创建于 ",el(c.createdAt)]})]})}),n.jsx("div",{className:"channel-card-head-actions",children:r?n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"primary-button compact-button",onClick:_,disabled:b||!O.trim(),children:b?"保存中":"保存"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>{K(c.name),T(c.description),E(!1)},children:"取消"})]}):n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>E(!0),children:"重命名"}),n.jsx("button",{className:"danger-button compact-button",onClick:()=>y(c.id),children:"删除"})]})})]})})}function lt({title:c,children:m}){return n.jsxs("section",{className:"panel",children:[n.jsx("div",{className:"panel-title",children:n.jsx("h2",{children:c})}),m]})}function Dt({tone:c,children:m}){return n.jsx("span",{className:`badge tone-${c}`,children:m})}function Pt({label:c,value:m,switchOn:y}){return n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:c}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:m}),typeof y=="boolean"&&n.jsx("div",{className:y?"ios-switch is-on":"ios-switch","aria-hidden":"true",children:n.jsx("span",{})})]})]})}function qp({value:c,options:m,onChange:y}){return n.jsx("div",{className:"segmented-control",children:m.map(r=>n.jsx("button",{className:c===r.value?"selected":"",onClick:()=>y(r.value),children:r.label},r.value))})}function Qt({text:c}){return n.jsx("div",{className:"empty",children:c})}k0.createRoot(document.getElementById("root")).render(n.jsx(G0.StrictMode,{children:n.jsx(op,{})})); diff --git a/dist/assets/index-CkIGdnVN.js b/dist/assets/index-CkIGdnVN.js deleted file mode 100644 index 1f81653..0000000 --- a/dist/assets/index-CkIGdnVN.js +++ /dev/null @@ -1,43 +0,0 @@ -(function(){const m=document.createElement("link").relList;if(m&&m.supports&&m.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))r(O);new MutationObserver(O=>{for(const R of O)if(R.type==="childList")for(const L of R.addedNodes)L.tagName==="LINK"&&L.rel==="modulepreload"&&r(L)}).observe(document,{childList:!0,subtree:!0});function p(O){const R={};return O.integrity&&(R.integrity=O.integrity),O.referrerPolicy&&(R.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?R.credentials="include":O.crossOrigin==="anonymous"?R.credentials="omit":R.credentials="same-origin",R}function r(O){if(O.ep)return;O.ep=!0;const R=p(O);fetch(O.href,R)}})();function H0(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var Xc={exports:{}},ai={};var em;function w0(){if(em)return ai;em=1;var c=Symbol.for("react.transitional.element"),m=Symbol.for("react.fragment");function p(r,O,R){var L=null;if(R!==void 0&&(L=""+R),O.key!==void 0&&(L=""+O.key),"key"in O){R={};for(var P in O)P!=="key"&&(R[P]=O[P])}else R=O;return O=R.ref,{$$typeof:c,type:r,key:L,ref:O!==void 0?O:null,props:R}}return ai.Fragment=m,ai.jsx=p,ai.jsxs=p,ai}var tm;function B0(){return tm||(tm=1,Xc.exports=w0()),Xc.exports}var n=B0(),Kc={exports:{}},Se={};var lm;function q0(){if(lm)return Se;lm=1;var c=Symbol.for("react.transitional.element"),m=Symbol.for("react.portal"),p=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),R=Symbol.for("react.consumer"),L=Symbol.for("react.context"),P=Symbol.for("react.forward_ref"),z=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),_=Symbol.for("react.activity"),ee=Symbol.iterator;function te(d){return d===null||typeof d!="object"?null:(d=ee&&d[ee]||d["@@iterator"],typeof d=="function"?d:null)}var fe={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},le=Object.assign,se={};function ie(d,M,G){this.props=d,this.context=M,this.refs=se,this.updater=G||fe}ie.prototype.isReactComponent={},ie.prototype.setState=function(d,M){if(typeof d!="object"&&typeof d!="function"&&d!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,d,M,"setState")},ie.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function ge(){}ge.prototype=ie.prototype;function re(d,M,G){this.props=d,this.context=M,this.refs=se,this.updater=G||fe}var Ne=re.prototype=new ge;Ne.constructor=re,le(Ne,ie.prototype),Ne.isPureReactComponent=!0;var $=Array.isArray;function ve(){}var U={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function ce(d,M,G){var X=G.ref;return{$$typeof:c,type:d,key:M,ref:X!==void 0?X:null,props:G}}function xe(d,M){return ce(d.type,M,d.props)}function Te(d){return typeof d=="object"&&d!==null&&d.$$typeof===c}function ae(d){var M={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(G){return M[G]})}var Q=/\/+/g;function me(d,M){return typeof d=="object"&&d!==null&&d.key!=null?ae(""+d.key):M.toString(36)}function Z(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(ve,ve):(d.status="pending",d.then(function(M){d.status==="pending"&&(d.status="fulfilled",d.value=M)},function(M){d.status==="pending"&&(d.status="rejected",d.reason=M)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function C(d,M,G,X,A){var I=typeof d;(I==="undefined"||I==="boolean")&&(d=null);var oe=!1;if(d===null)oe=!0;else switch(I){case"bigint":case"string":case"number":oe=!0;break;case"object":switch(d.$$typeof){case c:case m:oe=!0;break;case q:return oe=d._init,C(oe(d._payload),M,G,X,A)}}if(oe)return A=A(d),oe=X===""?"."+me(d,0):X,$(A)?(G="",oe!=null&&(G=oe.replace(Q,"$&/")+"/"),C(A,M,G,"",function(dt){return dt})):A!=null&&(Te(A)&&(A=xe(A,G+(A.key==null||d&&d.key===A.key?"":(""+A.key).replace(Q,"$&/")+"/")+oe)),M.push(A)),1;oe=0;var Qe=X===""?".":X+":";if($(d))for(var He=0;He>>1,k=C[T];if(0>>1;TO(G,y))XO(A,G)?(C[T]=A,C[X]=y,T=X):(C[T]=G,C[M]=y,T=M);else if(XO(A,y))C[T]=A,C[X]=y,T=X;else break e}}return Y}function O(C,Y){var y=C.sortIndex-Y.sortIndex;return y!==0?y:C.id-Y.id}if(c.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var R=performance;c.unstable_now=function(){return R.now()}}else{var L=Date,P=L.now();c.unstable_now=function(){return L.now()-P}}var z=[],g=[],q=1,_=null,ee=3,te=!1,fe=!1,le=!1,se=!1,ie=typeof setTimeout=="function"?setTimeout:null,ge=typeof clearTimeout=="function"?clearTimeout:null,re=typeof setImmediate<"u"?setImmediate:null;function Ne(C){for(var Y=p(g);Y!==null;){if(Y.callback===null)r(g);else if(Y.startTime<=C)r(g),Y.sortIndex=Y.expirationTime,m(z,Y);else break;Y=p(g)}}function $(C){if(le=!1,Ne(C),!fe)if(p(z)!==null)fe=!0,ve||(ve=!0,ae());else{var Y=p(g);Y!==null&&Z($,Y.startTime-C)}}var ve=!1,U=-1,F=5,ce=-1;function xe(){return se?!0:!(c.unstable_now()-ceC&&xe());){var T=_.callback;if(typeof T=="function"){_.callback=null,ee=_.priorityLevel;var k=T(_.expirationTime<=C);if(C=c.unstable_now(),typeof k=="function"){_.callback=k,Ne(C),Y=!0;break t}_===p(z)&&r(z),Ne(C)}else r(z);_=p(z)}if(_!==null)Y=!0;else{var d=p(g);d!==null&&Z($,d.startTime-C),Y=!1}}break e}finally{_=null,ee=y,te=!1}Y=void 0}}finally{Y?ae():ve=!1}}}var ae;if(typeof re=="function")ae=function(){re(Te)};else if(typeof MessageChannel<"u"){var Q=new MessageChannel,me=Q.port2;Q.port1.onmessage=Te,ae=function(){me.postMessage(null)}}else ae=function(){ie(Te,0)};function Z(C,Y){U=ie(function(){C(c.unstable_now())},Y)}c.unstable_IdlePriority=5,c.unstable_ImmediatePriority=1,c.unstable_LowPriority=4,c.unstable_NormalPriority=3,c.unstable_Profiling=null,c.unstable_UserBlockingPriority=2,c.unstable_cancelCallback=function(C){C.callback=null},c.unstable_forceFrameRate=function(C){0>C||125T?(C.sortIndex=y,m(g,C),p(z)===null&&C===p(g)&&(le?(ge(U),U=-1):le=!0,Z($,y-T))):(C.sortIndex=k,m(z,C),fe||te||(fe=!0,ve||(ve=!0,ae()))),C},c.unstable_shouldYield=xe,c.unstable_wrapCallback=function(C){var Y=ee;return function(){var y=ee;ee=Y;try{return C.apply(this,arguments)}finally{ee=y}}}})(Vc)),Vc}var im;function L0(){return im||(im=1,kc.exports=Y0()),kc.exports}var Jc={exports:{}},yt={};var sm;function Q0(){if(sm)return yt;sm=1;var c=Pc();function m(z){var g="https://react.dev/errors/"+z;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(m){console.error(m)}}return c(),Jc.exports=Q0(),Jc.exports}var cm;function K0(){if(cm)return ni;cm=1;var c=L0(),m=Pc(),p=X0();function r(e){var t="https://react.dev/errors/"+e;if(1k||(e.current=T[k],T[k]=null,k--)}function G(e,t){k++,T[k]=e.current,e.current=t}var X=d(null),A=d(null),I=d(null),oe=d(null);function Qe(e,t){switch(G(I,t),G(A,e),G(X,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Nf(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Nf(t),e=Af(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}M(X),G(X,e)}function He(){M(X),M(A),M(I)}function dt(e){e.memoizedState!==null&&G(oe,e);var t=X.current,l=Af(t,e.type);t!==l&&(G(A,e),G(X,l))}function V(e){A.current===e&&(M(X),M(A)),oe.current===e&&(M(oe),Pn._currentValue=y)}var Je,ut;function Pe(e){if(Je===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);Je=t&&t[1]||"",ut=-1)":-1i||f[a]!==S[i]){var D=` -`+f[a].replace(" at new "," at ");return e.displayName&&D.includes("")&&(D=D.replace("",e.displayName)),D}while(1<=a&&0<=i);break}}}finally{Ft=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Pe(l):""}function je(e,t){switch(e.tag){case 26:case 27:case 5:return Pe(e.type);case 16:return Pe("Lazy");case 13:return e.child!==t&&t!==null?Pe("Suspense Fallback"):Pe("Suspense");case 19:return Pe("SuspenseList");case 0:case 15:return v(e.type,!1);case 11:return v(e.type.render,!1);case 1:return v(e.type,!0);case 31:return Pe("Activity");default:return""}}function $e(e){try{var t="",l=null;do t+=je(e,l),l=e,e=e.return;while(e);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var Ke=Object.prototype.hasOwnProperty,il=c.unstable_scheduleCallback,It=c.unstable_cancelCallback,Es=c.unstable_shouldYield,Ms=c.unstable_requestPaint,bt=c.unstable_now,zs=c.unstable_getCurrentPriorityLevel,dn=c.unstable_ImmediatePriority,la=c.unstable_UserBlockingPriority,aa=c.unstable_NormalPriority,Os=c.unstable_LowPriority,H=c.unstable_IdlePriority,K=c.log,W=c.unstable_setDisableYieldValue,J=null,he=null;function we(e){if(typeof K=="function"&&W(e),he&&typeof he.setStrictMode=="function")try{he.setStrictMode(J,e)}catch{}}var Ze=Math.clz32?Math.clz32:na,Ot=Math.log,Ol=Math.LN2;function na(e){return e>>>=0,e===0?32:31-(Ot(e)/Ol|0)|0}var Aa=256,Ca=262144,_l=4194304;function rl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ui(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var i=0,s=e.suspendedLanes,u=e.pingedLanes;e=e.warmLanes;var o=a&134217727;return o!==0?(a=o&~s,a!==0?i=rl(a):(u&=o,u!==0?i=rl(u):l||(l=o&~e,l!==0&&(i=rl(l))))):(o=a&~s,o!==0?i=rl(o):u!==0?i=rl(u):l||(l=a&~e,l!==0&&(i=rl(l)))),i===0?0:t!==0&&t!==i&&(t&s)===0&&(s=i&-i,l=t&-t,s>=l||s===32&&(l&4194048)!==0)?t:i}function fn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Sm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function lo(){var e=_l;return _l<<=1,(_l&62914560)===0&&(_l=4194304),e}function _s(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function mn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Nm(e,t,l,a,i,s){var u=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var o=e.entanglements,f=e.expirationTimes,S=e.hiddenUpdates;for(l=u&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var zm=/[\n"\\]/g;function Yt(e){return e.replace(zm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Bs(e,t,l,a,i,s,u,o){e.name="",u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"?e.type=u:e.removeAttribute("type"),t!=null?u==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+Gt(t)):e.value!==""+Gt(t)&&(e.value=""+Gt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?qs(e,u,Gt(t)):l!=null?qs(e,u,Gt(l)):a!=null&&e.removeAttribute("value"),i==null&&s!=null&&(e.defaultChecked=!!s),i!=null&&(e.checked=i&&typeof i!="function"&&typeof i!="symbol"),o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.name=""+Gt(o):e.removeAttribute("name")}function vo(e,t,l,a,i,s,u,o){if(s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"&&(e.type=s),t!=null||l!=null){if(!(s!=="submit"&&s!=="reset"||t!=null)){ws(e);return}l=l!=null?""+Gt(l):"",t=t!=null?""+Gt(t):l,o||t===e.value||(e.value=t),e.defaultValue=t}a=a??i,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=o?e.checked:!!a,e.defaultChecked=!!a,u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.name=u),ws(e)}function qs(e,t,l){t==="number"&&ri(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function _a(e,t,l,a){if(e=e.options,t){t={};for(var i=0;i"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Xs=!1;if(ml)try{var yn={};Object.defineProperty(yn,"passive",{get:function(){Xs=!0}}),window.addEventListener("test",yn,yn),window.removeEventListener("test",yn,yn)}catch{Xs=!1}var Ul=null,Ks=null,fi=null;function No(){if(fi)return fi;var e,t=Ks,l=t.length,a,i="value"in Ul?Ul.value:Ul.textContent,s=i.length;for(e=0;e=xn),zo=" ",Oo=!1;function _o(e,t){switch(e){case"keyup":return ah.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Do(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ha=!1;function ih(e,t){switch(e){case"compositionend":return Do(t);case"keypress":return t.which!==32?null:(Oo=!0,zo);case"textInput":return e=t.data,e===zo&&Oo?null:e;default:return null}}function sh(e,t){if(Ha)return e==="compositionend"||!$s&&_o(e,t)?(e=No(),fi=Ks=Ul=null,Ha=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Yo(l)}}function Qo(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Qo(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Xo(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=ri(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=ri(e.document)}return t}function Is(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var hh=ml&&"documentMode"in document&&11>=document.documentMode,wa=null,Ps=null,An=null,eu=!1;function Ko(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;eu||wa==null||wa!==ri(a)||(a=wa,"selectionStart"in a&&Is(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),An&&Nn(An,a)||(An=a,a=is(Ps,"onSelect"),0>=u,i-=u,sl=1<<32-Ze(t)+i|l<Ce?(Oe=ue,ue=null):Oe=ue.sibling;var Ue=N(b,ue,j[Ce],w);if(Ue===null){ue===null&&(ue=Oe);break}e&&ue&&Ue.alternate===null&&t(b,ue),h=s(Ue,h,Ce),De===null?de=Ue:De.sibling=Ue,De=Ue,ue=Oe}if(Ce===j.length)return l(b,ue),_e&&pl(b,Ce),de;if(ue===null){for(;CeCe?(Oe=ue,ue=null):Oe=ue.sibling;var ta=N(b,ue,Ue.value,w);if(ta===null){ue===null&&(ue=Oe);break}e&&ue&&ta.alternate===null&&t(b,ue),h=s(ta,h,Ce),De===null?de=ta:De.sibling=ta,De=ta,ue=Oe}if(Ue.done)return l(b,ue),_e&&pl(b,Ce),de;if(ue===null){for(;!Ue.done;Ce++,Ue=j.next())Ue=B(b,Ue.value,w),Ue!==null&&(h=s(Ue,h,Ce),De===null?de=Ue:De.sibling=Ue,De=Ue);return _e&&pl(b,Ce),de}for(ue=a(ue);!Ue.done;Ce++,Ue=j.next())Ue=E(ue,b,Ce,Ue.value,w),Ue!==null&&(e&&Ue.alternate!==null&&ue.delete(Ue.key===null?Ce:Ue.key),h=s(Ue,h,Ce),De===null?de=Ue:De.sibling=Ue,De=Ue);return e&&ue.forEach(function(R0){return t(b,R0)}),_e&&pl(b,Ce),de}function Le(b,h,j,w){if(typeof j=="object"&&j!==null&&j.type===le&&j.key===null&&(j=j.props.children),typeof j=="object"&&j!==null){switch(j.$$typeof){case te:e:{for(var de=j.key;h!==null;){if(h.key===de){if(de=j.type,de===le){if(h.tag===7){l(b,h.sibling),w=i(h,j.props.children),w.return=b,b=w;break e}}else if(h.elementType===de||typeof de=="object"&&de!==null&&de.$$typeof===F&&pa(de)===h.type){l(b,h.sibling),w=i(h,j.props),On(w,j),w.return=b,b=w;break e}l(b,h);break}else t(b,h);h=h.sibling}j.type===le?(w=ra(j.props.children,b.mode,w,j.key),w.return=b,b=w):(w=Si(j.type,j.key,j.props,null,b.mode,w),On(w,j),w.return=b,b=w)}return u(b);case fe:e:{for(de=j.key;h!==null;){if(h.key===de)if(h.tag===4&&h.stateNode.containerInfo===j.containerInfo&&h.stateNode.implementation===j.implementation){l(b,h.sibling),w=i(h,j.children||[]),w.return=b,b=w;break e}else{l(b,h);break}else t(b,h);h=h.sibling}w=uu(j,b.mode,w),w.return=b,b=w}return u(b);case F:return j=pa(j),Le(b,h,j,w)}if(Z(j))return ne(b,h,j,w);if(ae(j)){if(de=ae(j),typeof de!="function")throw Error(r(150));return j=de.call(j),ye(b,h,j,w)}if(typeof j.then=="function")return Le(b,h,zi(j),w);if(j.$$typeof===re)return Le(b,h,Ci(b,j),w);Oi(b,j)}return typeof j=="string"&&j!==""||typeof j=="number"||typeof j=="bigint"?(j=""+j,h!==null&&h.tag===6?(l(b,h.sibling),w=i(h,j),w.return=b,b=w):(l(b,h),w=su(j,b.mode,w),w.return=b,b=w),u(b)):l(b,h)}return function(b,h,j,w){try{zn=0;var de=Le(b,h,j,w);return Va=null,de}catch(ue){if(ue===ka||ue===Ei)throw ue;var De=Dt(29,ue,null,b.mode);return De.lanes=w,De.return=b,De}}}var ya=mr(!0),hr=mr(!1),ql=!1;function gu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xu(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Gl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Yl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(Re&2)!==0){var i=a.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),a.pending=t,t=ji(e),Fo(e,null,l),t}return xi(e,a,t,l),ji(e)}function _n(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,no(e,l)}}function ju(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var i=null,s=null;if(l=l.firstBaseUpdate,l!==null){do{var u={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};s===null?i=s=u:s=s.next=u,l=l.next}while(l!==null);s===null?i=s=t:s=s.next=t}else i=s=t;l={baseState:a.baseState,firstBaseUpdate:i,lastBaseUpdate:s,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Su=!1;function Dn(){if(Su){var e=Za;if(e!==null)throw e}}function Un(e,t,l,a){Su=!1;var i=e.updateQueue;ql=!1;var s=i.firstBaseUpdate,u=i.lastBaseUpdate,o=i.shared.pending;if(o!==null){i.shared.pending=null;var f=o,S=f.next;f.next=null,u===null?s=S:u.next=S,u=f;var D=e.alternate;D!==null&&(D=D.updateQueue,o=D.lastBaseUpdate,o!==u&&(o===null?D.firstBaseUpdate=S:o.next=S,D.lastBaseUpdate=f))}if(s!==null){var B=i.baseState;u=0,D=S=f=null,o=s;do{var N=o.lane&-536870913,E=N!==o.lane;if(E?(ze&N)===N:(a&N)===N){N!==0&&N===Ka&&(Su=!0),D!==null&&(D=D.next={lane:0,tag:o.tag,payload:o.payload,callback:null,next:null});e:{var ne=e,ye=o;N=t;var Le=l;switch(ye.tag){case 1:if(ne=ye.payload,typeof ne=="function"){B=ne.call(Le,B,N);break e}B=ne;break e;case 3:ne.flags=ne.flags&-65537|128;case 0:if(ne=ye.payload,N=typeof ne=="function"?ne.call(Le,B,N):ne,N==null)break e;B=_({},B,N);break e;case 2:ql=!0}}N=o.callback,N!==null&&(e.flags|=64,E&&(e.flags|=8192),E=i.callbacks,E===null?i.callbacks=[N]:E.push(N))}else E={lane:N,tag:o.tag,payload:o.payload,callback:o.callback,next:null},D===null?(S=D=E,f=B):D=D.next=E,u|=N;if(o=o.next,o===null){if(o=i.shared.pending,o===null)break;E=o,o=E.next,E.next=null,i.lastBaseUpdate=E,i.shared.pending=null}}while(!0);D===null&&(f=B),i.baseState=f,i.firstBaseUpdate=S,i.lastBaseUpdate=D,s===null&&(i.shared.lanes=0),Zl|=u,e.lanes=u,e.memoizedState=B}}function pr(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function vr(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;es?s:8;var u=C.T,o={};C.T=o,Lu(e,!1,t,l);try{var f=i(),S=C.S;if(S!==null&&S(o,f),f!==null&&typeof f=="object"&&typeof f.then=="function"){var D=Nh(f,a);wn(e,t,D,Bt(e))}else wn(e,t,a,Bt(e))}catch(B){wn(e,t,{then:function(){},status:"rejected",reason:B},Bt())}finally{Y.p=s,u!==null&&o.types!==null&&(u.types=o.types),C.T=u}}function zh(){}function Gu(e,t,l,a){if(e.tag!==5)throw Error(r(476));var i=Jr(e).queue;Vr(e,i,t,y,l===null?zh:function(){return $r(e),l(a)})}function Jr(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:y,baseState:y,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:gl,lastRenderedState:y},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:gl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function $r(e){var t=Jr(e);t.next===null&&(t=e.alternate.memoizedState),wn(e,t.next.queue,{},Bt())}function Yu(){return ht(Pn)}function Wr(){return tt().memoizedState}function Fr(){return tt().memoizedState}function Oh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Bt();e=Gl(l);var a=Yl(t,e,l);a!==null&&(Tt(a,t,l),_n(a,t,l)),t={cache:pu()},e.payload=t;return}t=t.return}}function _h(e,t,l){var a=Bt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Yi(e)?Pr(t,l):(l=nu(e,t,l,a),l!==null&&(Tt(l,e,a),ed(l,t,a)))}function Ir(e,t,l){var a=Bt();wn(e,t,l,a)}function wn(e,t,l,a){var i={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Yi(e))Pr(t,i);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var u=t.lastRenderedState,o=s(u,l);if(i.hasEagerState=!0,i.eagerState=o,_t(o,u))return xi(e,t,i,0),Xe===null&&gi(),!1}catch{}if(l=nu(e,t,i,a),l!==null)return Tt(l,e,a),ed(l,t,a),!0}return!1}function Lu(e,t,l,a){if(a={lane:2,revertLane:gc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Yi(e)){if(t)throw Error(r(479))}else t=nu(e,l,a,2),t!==null&&Tt(t,e,2)}function Yi(e){var t=e.alternate;return e===Ae||t!==null&&t===Ae}function Pr(e,t){$a=Ui=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function ed(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,no(e,l)}}var Bn={readContext:ht,use:wi,useCallback:Fe,useContext:Fe,useEffect:Fe,useImperativeHandle:Fe,useLayoutEffect:Fe,useInsertionEffect:Fe,useMemo:Fe,useReducer:Fe,useRef:Fe,useState:Fe,useDebugValue:Fe,useDeferredValue:Fe,useTransition:Fe,useSyncExternalStore:Fe,useId:Fe,useHostTransitionStatus:Fe,useFormState:Fe,useActionState:Fe,useOptimistic:Fe,useMemoCache:Fe,useCacheRefresh:Fe};Bn.useEffectEvent=Fe;var td={readContext:ht,use:wi,useCallback:function(e,t){return gt().memoizedState=[e,t===void 0?null:t],e},useContext:ht,useEffect:qr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,qi(4194308,4,Qr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return qi(4194308,4,e,t)},useInsertionEffect:function(e,t){qi(4,2,e,t)},useMemo:function(e,t){var l=gt();t=t===void 0?null:t;var a=e();if(ba){we(!0);try{e()}finally{we(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=gt();if(l!==void 0){var i=l(t);if(ba){we(!0);try{l(t)}finally{we(!1)}}}else i=t;return a.memoizedState=a.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},a.queue=e,e=e.dispatch=_h.bind(null,Ae,e),[a.memoizedState,e]},useRef:function(e){var t=gt();return e={current:e},t.memoizedState=e},useState:function(e){e=Ru(e);var t=e.queue,l=Ir.bind(null,Ae,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Bu,useDeferredValue:function(e,t){var l=gt();return qu(l,e,t)},useTransition:function(){var e=Ru(!1);return e=Vr.bind(null,Ae,e.queue,!0,!1),gt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=Ae,i=gt();if(_e){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Xe===null)throw Error(r(349));(ze&127)!==0||Sr(a,t,l)}i.memoizedState=l;var s={value:l,getSnapshot:t};return i.queue=s,qr(Ar.bind(null,a,s,e),[e]),a.flags|=2048,Fa(9,{destroy:void 0},Nr.bind(null,a,s,l,t),null),l},useId:function(){var e=gt(),t=Xe.identifierPrefix;if(_e){var l=ul,a=sl;l=(a&~(1<<32-Ze(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Ri++,0<\/script>",s=s.removeChild(s.firstChild);break;case"select":s=typeof a.is=="string"?u.createElement("select",{is:a.is}):u.createElement("select"),a.multiple?s.multiple=!0:a.size&&(s.size=a.size);break;default:s=typeof a.is=="string"?u.createElement(i,{is:a.is}):u.createElement(i)}}s[ft]=t,s[xt]=a;e:for(u=t.child;u!==null;){if(u.tag===5||u.tag===6)s.appendChild(u.stateNode);else if(u.tag!==4&&u.tag!==27&&u.child!==null){u.child.return=u,u=u.child;continue}if(u===t)break e;for(;u.sibling===null;){if(u.return===null||u.return===t)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}t.stateNode=s;e:switch(vt(s,i,a),i){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&jl(t)}}return Ve(t),tc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&jl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=I.current,Qa(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,i=mt,i!==null)switch(i.tag){case 27:case 5:a=i.memoizedProps}e[ft]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||jf(e.nodeValue,l)),e||wl(t,!0)}else e=ss(e).createTextNode(a),e[ft]=t,t.stateNode=e}return Ve(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Qa(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[ft]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),e=!1}else l=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Rt(t),t):(Rt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Ve(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Qa(t),a!==null&&a.dehydrated!==null){if(e===null){if(!i)throw Error(r(318));if(i=t.memoizedState,i=i!==null?i.dehydrated:null,!i)throw Error(r(317));i[ft]=t}else da(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ve(t),i=!1}else i=du(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(Rt(t),t):(Rt(t),null)}return Rt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,i=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(i=a.alternate.memoizedState.cachePool.pool),s=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(s=a.memoizedState.cachePool.pool),s!==i&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Zi(t,t.updateQueue),Ve(t),null);case 4:return He(),e===null&&Nc(t.stateNode.containerInfo),Ve(t),null;case 10:return yl(t.type),Ve(t),null;case 19:if(M(et),a=t.memoizedState,a===null)return Ve(t),null;if(i=(t.flags&128)!==0,s=a.rendering,s===null)if(i)Gn(a,!1);else{if(Ie!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(s=Di(e),s!==null){for(t.flags|=128,Gn(a,!1),e=s.updateQueue,t.updateQueue=e,Zi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Io(l,e),l=l.sibling;return G(et,et.current&1|2),_e&&pl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&bt()>Wi&&(t.flags|=128,i=!0,Gn(a,!1),t.lanes=4194304)}else{if(!i)if(e=Di(s),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Zi(t,e),Gn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!s.alternate&&!_e)return Ve(t),null}else 2*bt()-a.renderingStartTime>Wi&&l!==536870912&&(t.flags|=128,i=!0,Gn(a,!1),t.lanes=4194304);a.isBackwards?(s.sibling=t.child,t.child=s):(e=a.last,e!==null?e.sibling=s:t.child=s,a.last=s)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=bt(),e.sibling=null,l=et.current,G(et,i?l&1|2:l&1),_e&&pl(t,a.treeForkCount),e):(Ve(t),null);case 22:case 23:return Rt(t),Au(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Ve(t),t.subtreeFlags&6&&(t.flags|=8192)):Ve(t),l=t.updateQueue,l!==null&&Zi(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&M(ha),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),yl(at),Ve(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function wh(e,t){switch(ou(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return yl(at),He(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return V(t),null;case 31:if(t.memoizedState!==null){if(Rt(t),t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Rt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));da()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return M(et),null;case 4:return He(),null;case 10:return yl(t.type),null;case 22:case 23:return Rt(t),Au(),e!==null&&M(ha),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return yl(at),null;case 25:return null;default:return null}}function Cd(e,t){switch(ou(t),t.tag){case 3:yl(at),He();break;case 26:case 27:case 5:V(t);break;case 4:He();break;case 31:t.memoizedState!==null&&Rt(t);break;case 13:Rt(t);break;case 19:M(et);break;case 10:yl(t.type);break;case 22:case 23:Rt(t),Au(),e!==null&&M(ha);break;case 24:yl(at)}}function Yn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var i=a.next;l=i;do{if((l.tag&e)===e){a=void 0;var s=l.create,u=l.inst;a=s(),u.destroy=a}l=l.next}while(l!==i)}}catch(o){qe(t,t.return,o)}}function Xl(e,t,l){try{var a=t.updateQueue,i=a!==null?a.lastEffect:null;if(i!==null){var s=i.next;a=s;do{if((a.tag&e)===e){var u=a.inst,o=u.destroy;if(o!==void 0){u.destroy=void 0,i=t;var f=l,S=o;try{S()}catch(D){qe(i,f,D)}}}a=a.next}while(a!==s)}}catch(D){qe(t,t.return,D)}}function Td(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{vr(t,l)}catch(a){qe(e,e.return,a)}}}function Ed(e,t,l){l.props=ga(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){qe(e,t,a)}}function Ln(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(i){qe(e,t,i)}}function cl(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(i){qe(e,t,i)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(i){qe(e,t,i)}else l.current=null}function Md(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(i){qe(e,e.return,i)}}function lc(e,t,l){try{var a=e.stateNode;n0(a,e.type,l,t),a[xt]=t}catch(i){qe(e,e.return,i)}}function zd(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Wl(e.type)||e.tag===4}function ac(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||zd(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Wl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function nc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=fl));else if(a!==4&&(a===27&&Wl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(nc(e,t,l),e=e.sibling;e!==null;)nc(e,t,l),e=e.sibling}function ki(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Wl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(ki(e,t,l),e=e.sibling;e!==null;)ki(e,t,l),e=e.sibling}function Od(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);vt(t,a,l),t[ft]=e,t[xt]=l}catch(s){qe(e,e.return,s)}}var Sl=!1,st=!1,ic=!1,_d=typeof WeakSet=="function"?WeakSet:Set,rt=null;function Bh(e,t){if(e=e.containerInfo,Tc=ms,e=Xo(e),Is(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var i=a.anchorOffset,s=a.focusNode;a=a.focusOffset;try{l.nodeType,s.nodeType}catch{l=null;break e}var u=0,o=-1,f=-1,S=0,D=0,B=e,N=null;t:for(;;){for(var E;B!==l||i!==0&&B.nodeType!==3||(o=u+i),B!==s||a!==0&&B.nodeType!==3||(f=u+a),B.nodeType===3&&(u+=B.nodeValue.length),(E=B.firstChild)!==null;)N=B,B=E;for(;;){if(B===e)break t;if(N===l&&++S===i&&(o=u),N===s&&++D===a&&(f=u),(E=B.nextSibling)!==null)break;B=N,N=B.parentNode}B=E}l=o===-1||f===-1?null:{start:o,end:f}}else l=null}l=l||{start:0,end:0}}else l=null;for(Ec={focusedElem:e,selectionRange:l},ms=!1,rt=t;rt!==null;)if(t=rt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,rt=e;else for(;rt!==null;){switch(t=rt,s=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),vt(s,a,l),s[ft]=e,ot(s),a=s;break e;case"link":var u=qf("link","href",i).get(a+(l.href||""));if(u){for(var o=0;oLe&&(u=Le,Le=ye,ye=u);var b=Lo(o,ye),h=Lo(o,Le);if(b&&h&&(E.rangeCount!==1||E.anchorNode!==b.node||E.anchorOffset!==b.offset||E.focusNode!==h.node||E.focusOffset!==h.offset)){var j=B.createRange();j.setStart(b.node,b.offset),E.removeAllRanges(),ye>Le?(E.addRange(j),E.extend(h.node,h.offset)):(j.setEnd(h.node,h.offset),E.addRange(j))}}}}for(B=[],E=o;E=E.parentNode;)E.nodeType===1&&B.push({element:E,left:E.scrollLeft,top:E.scrollTop});for(typeof o.focus=="function"&&o.focus(),o=0;ol?32:l,C.T=null,l=fc,fc=null;var s=Vl,u=El;if(ct=0,ln=Vl=null,El=0,(Re&6)!==0)throw Error(r(331));var o=Re;if(Re|=4,Qd(s.current),Gd(s,s.current,u,l),Re=o,Vn(0,!1),he&&typeof he.onPostCommitFiberRoot=="function")try{he.onPostCommitFiberRoot(J,s)}catch{}return!0}finally{Y.p=i,C.T=a,uf(e,t)}}function of(e,t,l){t=Qt(l,t),t=Zu(e.stateNode,t,2),e=Yl(e,t,2),e!==null&&(mn(e,2),ol(e))}function qe(e,t,l){if(e.tag===3)of(e,e,l);else for(;t!==null;){if(t.tag===3){of(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(kl===null||!kl.has(a))){e=Qt(l,e),l=od(2),a=Yl(t,l,2),a!==null&&(rd(l,a,t,e),mn(a,2),ol(a));break}}t=t.return}}function vc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Yh;var i=new Set;a.set(t,i)}else i=a.get(t),i===void 0&&(i=new Set,a.set(t,i));i.has(l)||(cc=!0,i.add(l),e=Zh.bind(null,e,t,l),t.then(e,e))}function Zh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Xe===e&&(ze&l)===l&&(Ie===4||Ie===3&&(ze&62914560)===ze&&300>bt()-$i?(Re&2)===0&&an(e,0):oc|=l,tn===ze&&(tn=0)),ol(e)}function rf(e,t){t===0&&(t=lo()),e=oa(e,t),e!==null&&(mn(e,t),ol(e))}function kh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),rf(e,l)}function Vh(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,i=e.memoizedState;i!==null&&(l=i.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),rf(e,l)}function Jh(e,t){return il(e,t)}var ls=null,sn=null,yc=!1,as=!1,bc=!1,$l=0;function ol(e){e!==sn&&e.next===null&&(sn===null?ls=sn=e:sn=sn.next=e),as=!0,yc||(yc=!0,Wh())}function Vn(e,t){if(!bc&&as){bc=!0;do for(var l=!1,a=ls;a!==null;){if(e!==0){var i=a.pendingLanes;if(i===0)var s=0;else{var u=a.suspendedLanes,o=a.pingedLanes;s=(1<<31-Ze(42|e)+1)-1,s&=i&~(u&~o),s=s&201326741?s&201326741|1:s?s|2:0}s!==0&&(l=!0,hf(a,s))}else s=ze,s=ui(a,a===Xe?s:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(s&3)===0||fn(a,s)||(l=!0,hf(a,s));a=a.next}while(l);bc=!1}}function $h(){df()}function df(){as=yc=!1;var e=0;$l!==0&&s0()&&(e=$l);for(var t=bt(),l=null,a=ls;a!==null;){var i=a.next,s=ff(a,t);s===0?(a.next=null,l===null?ls=i:l.next=i,i===null&&(sn=l)):(l=a,(e!==0||(s&3)!==0)&&(as=!0)),a=i}ct!==0&&ct!==5||Vn(e),$l!==0&&($l=0)}function ff(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,i=e.expirationTimes,s=e.pendingLanes&-62914561;0o)break;var D=f.transferSize,B=f.initiatorType;D&&Sf(B)&&(f=f.responseEnd,u+=D*(f"u"?null:document;function Rf(e,t,l){var a=un;if(a&&typeof t=="string"&&t){var i=Yt(t);i='link[rel="'+e+'"][href="'+i+'"]',typeof l=="string"&&(i+='[crossorigin="'+l+'"]'),Uf.has(i)||(Uf.add(i),e={rel:e,crossOrigin:l,href:t},a.querySelector(i)===null&&(t=a.createElement("link"),vt(t,"link",e),ot(t),a.head.appendChild(t)))}}function p0(e){Ml.D(e),Rf("dns-prefetch",e,null)}function v0(e,t){Ml.C(e,t),Rf("preconnect",e,t)}function y0(e,t,l){Ml.L(e,t,l);var a=un;if(a&&e&&t){var i='link[rel="preload"][as="'+Yt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(i+='[imagesrcset="'+Yt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(i+='[imagesizes="'+Yt(l.imageSizes)+'"]')):i+='[href="'+Yt(e)+'"]';var s=i;switch(t){case"style":s=cn(e);break;case"script":s=on(e)}Jt.has(s)||(e=_({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Jt.set(s,e),a.querySelector(i)!==null||t==="style"&&a.querySelector(Fn(s))||t==="script"&&a.querySelector(In(s))||(t=a.createElement("link"),vt(t,"link",e),ot(t),a.head.appendChild(t)))}}function b0(e,t){Ml.m(e,t);var l=un;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",i='link[rel="modulepreload"][as="'+Yt(a)+'"][href="'+Yt(e)+'"]',s=i;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":s=on(e)}if(!Jt.has(s)&&(e=_({rel:"modulepreload",href:e},t),Jt.set(s,e),l.querySelector(i)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(In(s)))return}a=l.createElement("link"),vt(a,"link",e),ot(a),l.head.appendChild(a)}}}function g0(e,t,l){Ml.S(e,t,l);var a=un;if(a&&e){var i=za(a).hoistableStyles,s=cn(e);t=t||"default";var u=i.get(s);if(!u){var o={loading:0,preload:null};if(u=a.querySelector(Fn(s)))o.loading=5;else{e=_({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Jt.get(s))&&Rc(e,l);var f=u=a.createElement("link");ot(f),vt(f,"link",e),f._p=new Promise(function(S,D){f.onload=S,f.onerror=D}),f.addEventListener("load",function(){o.loading|=1}),f.addEventListener("error",function(){o.loading|=2}),o.loading|=4,cs(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:o},i.set(s,u)}}}function x0(e,t){Ml.X(e,t);var l=un;if(l&&e){var a=za(l).hoistableScripts,i=on(e),s=a.get(i);s||(s=l.querySelector(In(i)),s||(e=_({src:e,async:!0},t),(t=Jt.get(i))&&Hc(e,t),s=l.createElement("script"),ot(s),vt(s,"link",e),l.head.appendChild(s)),s={type:"script",instance:s,count:1,state:null},a.set(i,s))}}function j0(e,t){Ml.M(e,t);var l=un;if(l&&e){var a=za(l).hoistableScripts,i=on(e),s=a.get(i);s||(s=l.querySelector(In(i)),s||(e=_({src:e,async:!0,type:"module"},t),(t=Jt.get(i))&&Hc(e,t),s=l.createElement("script"),ot(s),vt(s,"link",e),l.head.appendChild(s)),s={type:"script",instance:s,count:1,state:null},a.set(i,s))}}function Hf(e,t,l,a){var i=(i=I.current)?us(i):null;if(!i)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=cn(l.href),l=za(i).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=cn(l.href);var s=za(i).hoistableStyles,u=s.get(e);if(u||(i=i.ownerDocument||i,u={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},s.set(e,u),(s=i.querySelector(Fn(e)))&&!s._p&&(u.instance=s,u.state.loading=5),Jt.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Jt.set(e,l),s||S0(i,e,l,u.state))),t&&a===null)throw Error(r(528,""));return u}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=on(l),l=za(i).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function cn(e){return'href="'+Yt(e)+'"'}function Fn(e){return'link[rel="stylesheet"]['+e+"]"}function wf(e){return _({},e,{"data-precedence":e.precedence,precedence:null})}function S0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),vt(t,"link",l),ot(t),e.head.appendChild(t))}function on(e){return'[src="'+Yt(e)+'"]'}function In(e){return"script[async]"+e}function Bf(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Yt(l.href)+'"]');if(a)return t.instance=a,ot(a),a;var i=_({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),ot(a),vt(a,"style",i),cs(a,l.precedence,e),t.instance=a;case"stylesheet":i=cn(l.href);var s=e.querySelector(Fn(i));if(s)return t.state.loading|=4,t.instance=s,ot(s),s;a=wf(l),(i=Jt.get(i))&&Rc(a,i),s=(e.ownerDocument||e).createElement("link"),ot(s);var u=s;return u._p=new Promise(function(o,f){u.onload=o,u.onerror=f}),vt(s,"link",a),t.state.loading|=4,cs(s,l.precedence,e),t.instance=s;case"script":return s=on(l.src),(i=e.querySelector(In(s)))?(t.instance=i,ot(i),i):(a=l,(i=Jt.get(s))&&(a=_({},l),Hc(a,i)),e=e.ownerDocument||e,i=e.createElement("script"),ot(i),vt(i,"link",a),e.head.appendChild(i),t.instance=i);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,cs(a,l.precedence,e));return t.instance}function cs(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),i=a.length?a[a.length-1]:null,s=i,u=0;u title"):null)}function N0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Yf(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function A0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var i=cn(a.href),s=t.querySelector(Fn(i));if(s){t=s._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=rs.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=s,ot(s);return}s=t.ownerDocument||t,a=wf(a),(i=Jt.get(i))&&Rc(a,i),s=s.createElement("link"),ot(s);var u=s;u._p=new Promise(function(o,f){u.onload=o,u.onerror=f}),vt(s,"link",a),l.instance=s}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=rs.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var wc=0;function C0(e,t){return e.stylesheets&&e.count===0&&fs(e,e.stylesheets),0wc?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(i)}}:null}function rs(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)fs(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var ds=null;function fs(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ds=new Map,t.forEach(T0,e),ds=null,rs.call(e))}function T0(e,t){if(!(t.state.loading&4)){var l=ds.get(e);if(l)var a=l.get(null);else{l=new Map,ds.set(e,l);for(var i=e.querySelectorAll("link[data-precedence],style[data-precedence]"),s=0;s"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(m){console.error(m)}}return c(),Zc.exports=K0(),Zc.exports}var k0=Z0();function be(c){return Array.isArray(c)?c:[]}function hm(c){const m=new Set;return c.map(p=>p.trim()).filter(p=>{const r=p.toLowerCase();return!p||m.has(r)?!1:(m.add(r),!0)})}function ll(c){const m=js.some(p=>p.value===c.streamMode)?c.streamMode:"auto";return{...c,streamMode:m,models:be(c.models),allowedGroupIds:be(c.allowedGroupIds),openaiAccounts:be(c.openaiAccounts),kiroAccounts:be(c.kiroAccounts)}}function ii(c){return{...c,aliases:be(c.aliases)}}function V0(c){return{...c,apiKeys:be(c.apiKeys),logs:be(c.logs)}}class Ns extends Error{status;payload;constructor(m,p,r){super(p),this.status=m,this.payload=r}}const J0={home:"M3 10.5 12 3l9 7.5V21a1 1 0 0 1-1 1h-5v-7H9v7H4a1 1 0 0 1-1-1z",users:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",key:"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.78 7.78 5.5 5.5 0 0 1 7.78-7.78ZM14 8l7-7M21 8h-5V3",models:"M12 2 4 6v12l8 4 8-4V6zM4 6l8 4 8-4M12 10v12",image:"M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2ZM8.5 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM21 16l-5-5L5 21",route:"M4 19a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM20 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM7 16h3a4 4 0 0 0 4-4V8h3",logs:"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M8 13h8M8 17h6",settings:"M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 8.92 4a1.65 1.65 0 0 0 1-1.51V2a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.31.39.57.71.71.23.1.49.18.8.2H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z",search:"M21 21l-4.35-4.35M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z",copy:"M8 8h11a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1ZM4 16H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v1",ban:"M4.93 4.93 19.07 19.07M22 12A10 10 0 1 1 2 12a10 10 0 0 1 20 0Z",check:"M20 6 9 17l-5-5",moon:"M21 12.8A8.5 8.5 0 1 1 11.2 3 6.5 6.5 0 0 0 21 12.8Z",sun:"M12 4V2M12 22v-2M4.93 4.93 3.52 3.52M20.48 20.48l-1.41-1.41M4 12H2M22 12h-2M4.93 19.07l-1.41 1.41M20.48 3.52l-1.41 1.41M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z",plus:"M12 5v14M5 12h14"};function Et({name:c}){return n.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",className:"icon",children:n.jsx("path",{d:J0[c]})})}async function pe(c,m){const p=new Headers(m?.headers);p.set("Content-Type","application/json");const r=window.sessionStorage.getItem("capi-admin-token");r&&p.set("Authorization",`Bearer ${r}`);const O=await fetch(c,{credentials:"include",...m,headers:p});if(!O.ok){const R=await O.json().catch(()=>null);throw new Ns(O.status,R?.error?.message||`Request failed: ${O.status}`,R)}return O.json()}async function $0(c,m){const p=new Headers,r=window.sessionStorage.getItem("capi-admin-token");r&&p.set("Authorization",`Bearer ${r}`);const O=await fetch(c,{credentials:"include",method:"POST",headers:p,body:m});if(!O.ok){const R=await O.json().catch(()=>null);throw new Ns(O.status,R?.error?.message||`Request failed: ${O.status}`,R)}return O.json()}const rm=[{id:"overview",label:"概览",icon:"home"},{id:"users",label:"用户",icon:"users"},{id:"groups",label:"分组",icon:"users"},{id:"keys",label:"密钥",icon:"key"},{id:"models",label:"模型",icon:"models"},{id:"drawing",label:"绘图",icon:"image"},{id:"channels",label:"渠道",icon:"route"},{id:"logs",label:"日志",icon:"logs"},{id:"settings",label:"设置",icon:"settings"}],eo=[{value:"kiro",label:"Kiro / Amazon Q"},{value:"codex",label:"Codex / ChatGPT OAuth"},{value:"cpa",label:"CPA / CLIProxyAPI"},{value:"openai",label:"OpenAI"},{value:"anthropic",label:"Anthropic / Claude"},{value:"google",label:"Google Gemini"},{value:"deepseek",label:"DeepSeek"},{value:"openrouter",label:"OpenRouter"},{value:"groq",label:"Groq"},{value:"siliconflow",label:"SiliconFlow"},{value:"moonshot",label:"Moonshot"},{value:"compatible",label:"OpenAI 兼容接口"}],pm="https://api.openai.com/v1",As="https://chatgpt.com/backend-api",vm="http://localhost:8317/v1",ym="https://codewhisperer.us-east-1.amazonaws.com",bm="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2, gpt-image-1",W0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-image-2",F0="gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, claude-sonnet-4, gemini-3.1-pro",I0="claude-sonnet-4.5, claude-sonnet-4, claude-haiku-4.5, claude-opus-4.5",Fc=[{provider:"kiro",label:"Kiro / Amazon Q",name:"Kiro 账号池",baseUrl:ym,models:I0.split(",").map(c=>c.trim())},{provider:"openai",label:"OpenAI",name:"OpenAI 主线路",baseUrl:pm,models:W0.split(",").map(c=>c.trim())},{provider:"codex",label:"Codex 账号池",name:"Codex 账号池",baseUrl:As,models:bm.split(",").map(c=>c.trim())},{provider:"cpa",label:"CPA / CLIProxyAPI",name:"CPA 本地代理",baseUrl:vm,models:F0.split(",").map(c=>c.trim())},{provider:"compatible",label:"OpenAI 兼容接口",name:"兼容渠道",baseUrl:"",models:[]},{provider:"openrouter",label:"OpenRouter",name:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",models:[]},{provider:"google",label:"Google Gemini",name:"Gemini",baseUrl:"",models:[]},{provider:"anthropic",label:"Anthropic / Claude",name:"Claude",baseUrl:"",models:[]}];function Sa(c){return Fc.find(m=>m.provider===c)||Fc[2]}function gm(c){const m=Sa(c);return{name:m.name,provider:m.provider,baseUrl:m.baseUrl,models:[...m.models],streamMode:"auto"}}function P0(c){const m=c?.trim().toLowerCase();return m&&({free:"Free",plus:"Plus",pro:"Pro",team:"Team",enterprise:"Enterprise"}[m]||c)||"套餐未知"}function dm(c){return c?{upstream_token_invalidated:"Token 已失效",upstream_invalid_api_key:"API Key 无效",upstream_account_error:"账号错误",upstream_accounts_unavailable:"账号池不可用",upstream_error:"上游错误"}[c]||c:""}function Cs(c){return c==="openai"?pm:c==="codex"?As:c==="cpa"||c==="cliproxyapi"?vm:c==="kiro"?ym:""}function Ic(c){return hm(c.split(/[\s,;,;]+/))}function ep(c){return hm(c.split(/[\n,;,;]+/).map(m=>m.trim()))}function xm(c){const m=ep(c);return m.length===0?{}:m.length===1?{upstreamApiKey:m[0]}:{upstreamApiKeys:m}}const js=[{value:"auto",label:"自动",description:"按请求参数处理"},{value:"real",label:"真流",description:"直连上游 SSE"},{value:"fake",label:"假流",description:"非流转 SSE"},{value:"disabled",label:"禁用流",description:"流式请求跳过"}];function Wt(c){if(!c)return"未使用";const m=new Date(c);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(m)}function fm(c){if(!c)return"";const m=new Date(c);if(Number.isNaN(m.getTime()))return"";const p=m.getTimezoneOffset()*6e4;return new Date(m.getTime()-p).toISOString().slice(0,16)}function tp(c){if(!c)return"";const m=new Date(c);return Number.isNaN(m.getTime())?"":m.toISOString()}function lp(c){if(!c)return"-";const m=new Date(c);return Number.isNaN(m.getTime())?"-":new Intl.DateTimeFormat("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).format(m)}function Mt(c){return{active:"正常",disabled:"禁用",limited:"受限",overdue:"欠费",healthy:"正常",standby:"备用",available:"Available",success:"成功",failed:"失败"}[c]||c}function si(c,m=2){const p=Number(c||0);return new Intl.NumberFormat("zh-CN",{minimumFractionDigits:m,maximumFractionDigits:m}).format(p)}function Na(c){return new Intl.NumberFormat("zh-CN").format(Math.max(0,Math.round(Number(c||0))))}function to(c){return c.model?c.model:c.errorCode==="invalid_api_key"?"密钥无效":c.errorCode==="model_not_available"?"模型不可用":c.errorCode==="insufficient_quota"?"额度不足":c.errorCode==="rate_limit_exceeded"?"请求过快":c.errorCode||"请求失败"}function ap(c){return c.model||(c.errorCode?`错误:${c.errorCode}`:"-")}function np(c){return c.channel||(c.apiKeyPrefix?`Key ${c.apiKeyPrefix}`:"-")}function ip(c){const m=be(c);if(m.length===0)return"未绑定模型";const p=m.slice(0,2).join(", ");return m.length>2?`${p} · 其余 ${m.length-2} 个`:p}function al(c){return c==="cliproxyapi"||c==="cli-proxy-api"?"CPA / CLIProxyAPI":eo.find(m=>m.value===c)?.label||c||"Custom"}function $c(c){const m=`${c.vendor} ${c.id} ${c.name}`.toLowerCase();return m.includes("cliproxyapi")||/\bcpa\b/.test(m)?"cpa":m.includes("openai")||/\bgpt[-_/]/.test(m)||m.includes("o1-")||m.includes("o3-")?"openai":m.includes("anthropic")||m.includes("claude")?"anthropic":m.includes("google")||m.includes("gemini")||m.includes("gcli-")?"google":m.includes("deepseek")?"deepseek":m.includes("openrouter")?"openrouter":m.includes("groq")?"groq":m.includes("siliconflow")?"siliconflow":m.includes("moonshot")||m.includes("kimi")?"moonshot":c.vendor&&c.vendor.toLowerCase()!=="custom"?c.vendor.toLowerCase():"compatible"}function mm({provider:c}){if(c==="deepseek")return n.jsx("span",{className:"provider-icon provider-icon-deepseek","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("path",{transform:"translate(2.4 4.4)",d:"M26.517 3.395c-.282-.138-.403.125-.568.258-.057.044-.105.1-.152.152-.413.44-.895.73-1.524.695-.92-.052-1.705.237-2.4.941-.147-.868-.638-1.386-1.384-1.718-.39-.173-.786-.346-1.06-.721-.19-.268-.243-.566-.338-.86-.061-.176-.121-.357-.325-.388-.222-.034-.309.151-.396.307-.347.635-.481 1.334-.468 2.042.03 1.594.703 2.863 2.04 3.765.152.104.191.207.143.359-.091.31-.2.613-.295.924-.06.198-.151.242-.364.155-.734-.306-1.367-.76-1.927-1.308-.951-.92-1.81-1.934-2.882-2.729-.252-.185-.504-.358-.764-.522-1.094-1.062.143-1.935.43-2.038.3-.108.104-.48-.864-.475-.968.004-1.853.328-2.982.76-.165.065-.339.112-.516.151-1.024-.194-2.088-.237-3.199-.112-2.092.233-3.763 1.222-4.991 2.91C.254 7.972-.093 10.278.332 12.682c.446 2.535 1.74 4.633 3.728 6.274 2.062 1.7 4.436 2.534 7.145 2.375 1.645-.095 3.476-.316 5.542-2.064.521.259 1.068.363 1.975.44.699.065 1.371-.034 1.892-.142.816-.173.76-.929.465-1.067-2.392-1.114-1.866-.661-2.344-1.027 1.215-1.438 3.071-3.993 3.644-7.473.056-.384.128-.925.12-1.236-.005-.19.038-.263.255-.285.6-.069 1.18-.233 1.715-.527 1.55-.846 2.175-2.237 2.322-3.903.022-.255-.005-.518-.274-.652ZM13.014 18.395c-2.318-1.823-3.442-2.423-3.906-2.397-.434.026-.356.523-.26.847.1.32.23.54.412.82.126.186.213.462-.126.67-.746.461-2.044-.156-2.105-.186-1.51-.89-2.773-2.064-3.664-3.67-.86-1.545-1.358-3.204-1.44-4.974-.022-.427.104-.578.529-.656.56-.103 1.137-.125 1.697-.043 2.366.346 4.379 1.403 6.068 3.079.963.954 1.692 2.094 2.443 3.208.799 1.183 1.658 2.31 2.752 3.234.387.324.695.57.99.751-.89.1-2.374.121-3.39-.683Zm1.111-7.146c0-.19.152-.341.343-.341.043 0 .082.009.117.021.048.018.092.044.126.083.061.06.096.146.096.237a.341.341 0 0 1-.343.341.34.34 0 0 1-.339-.341Zm3.451 1.77c-.222.09-.443.168-.656.177-.33.017-.69-.117-.885-.281-.304-.255-.521-.397-.612-.842-.039-.19-.017-.483.017-.652.078-.362-.009-.595-.265-.807-.208-.172-.473-.22-.764-.22-.108 0-.208-.048-.282-.086-.121-.061-.221-.212-.126-.398.031-.06.178-.207.213-.233.395-.225.85-.151 1.272.018.39.16.686.453 1.111.867.434.501.512.639.759 1.015.196.294.373.596.495.942.073.215-.022.392-.277.5Z"})]})});if(c==="openai")return n.jsx("span",{className:"provider-icon provider-icon-openai","aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("g",{transform:"translate(7 7.5) scale(0.065)",fill:"currentColor",stroke:"none",children:n.jsx("path",{d:"M267.06 111.34a71.78 71.78 0 0 0-6.17-58.91c-14.5-25.15-43.55-38.09-71.9-32.03A71.78 71.78 0 0 0 135.1.5C106 .43 80.21 19.16 71.29 46.85a71.79 71.79 0 0 0-47.98 34.8c-14.6 25.1-11.28 56.75 8.22 78.3a71.78 71.78 0 0 0 6.16 58.9c14.5 25.16 43.56 38.1 71.91 32.04a71.76 71.76 0 0 0 53.89 24.02c29.12.02 54.92-18.72 63.84-46.44a71.79 71.79 0 0 0 47.98-34.8c14.58-25.1 11.25-56.72-8.24-78.27zm-107.9 150.77a53.15 53.15 0 0 1-34.15-12.35c.43-.24 1.2-.66 1.7-.96l56.68-32.73a9.22 9.22 0 0 0 4.66-8.06v-79.9l23.95 13.83a.85.85 0 0 1 .47.66v66.16a53.42 53.42 0 0 1-53.3 53.35zM44.6 213.16a53.13 53.13 0 0 1-6.36-35.75c.42.25 1.15.7 1.68 1l56.68 32.73a9.24 9.24 0 0 0 9.31 0l69.2-39.95v27.66a.87.87 0 0 1-.34.74l-57.29 33.07a53.42 53.42 0 0 1-72.88-19.5zM29.7 90.05a53.1 53.1 0 0 1 27.76-23.36c0 .49-.03 1.36-.03 1.96v65.46a9.22 9.22 0 0 0 4.65 8.05l69.2 39.95-23.95 13.83a.86.86 0 0 1-.81.07L49.2 162.9A53.42 53.42 0 0 1 29.7 90.05zm196.8 45.8L157.3 95.9l23.95-13.82a.86.86 0 0 1 .81-.07l57.3 33.08a53.37 53.37 0 0 1-8.24 96.29v-65.46a9.2 9.2 0 0 0-4.62-8.06zm23.84-35.89c-.42-.26-1.15-.7-1.68-1.01l-56.68-32.73a9.25 9.25 0 0 0-9.31 0l-69.2 39.95V78.5a.87.87 0 0 1 .35-.74l57.28-33.05a53.35 53.35 0 0 1 79.24 55.25zM100.11 149.24l-23.96-13.83a.85.85 0 0 1-.46-.66V68.6a53.37 53.37 0 0 1 87.52-40.95c-.42.24-1.19.66-1.7.96l-56.68 32.73a9.22 9.22 0 0 0-4.66 8.06l-.04 79.85zm13.01-28.05L144 103.3l30.88 17.83v35.68L144 174.63l-30.88-17.82v-35.62z"})})]})});const m=c==="codex"?"C":c==="cpa"||c==="cliproxyapi"?"CPA":c==="anthropic"?"A":c==="google"?"✦":c==="openrouter"?"↗":c==="groq"?"G":c==="siliconflow"?"S":c==="moonshot"?"M":"◇";return n.jsx("span",{className:`provider-icon provider-icon-${c}`,"aria-hidden":"true",children:n.jsxs("svg",{viewBox:"0 0 32 32",role:"img",children:[n.jsx("rect",{x:"1",y:"1",width:"30",height:"30",rx:"8"}),n.jsx("text",{x:"16",y:"21",textAnchor:"middle",children:m})]})})}async function Ss(c){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(c);return}const m=document.createElement("textarea");m.value=c,m.setAttribute("readonly","true"),m.style.position="fixed",m.style.opacity="0",document.body.appendChild(m),m.select(),document.execCommand("copy"),document.body.removeChild(m)}function zl(){return window.location.origin}function sp(){return`${zl()}/api/auth/discord/callback`}function up(){return`${zl()}/`}function Wc(c){return{...c,redirectUri:c.redirectUri&&!c.redirectUri.includes("localhost")?c.redirectUri:sp(),authSuccessUrl:c.authSuccessUrl&&!c.authSuccessUrl.includes("localhost")?c.authSuccessUrl:up(),blockedGuildIds:be(c.blockedGuildIds),sessionTtlHours:c.sessionTtlHours||168}}function Ts(c){return c==="email"||c==="discord"?c:"username"}function cp(c){const p=(c.split("@")[0]||"user").toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^[-_]+|[-_]+$/g,"");return(p.length>=3?p:"user").slice(0,24)}function op(){const[c,m]=x.useState("home"),[p,r]=x.useState("login"),[O,R]=x.useState(null),[L,P]=x.useState("overview"),[z,g]=x.useState(()=>{const H=window.localStorage.getItem("capi-theme");return H==="light"||H==="dark"?H:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}),[q,_]=x.useState("comfortable"),[ee,te]=x.useState(null),[fe,le]=x.useState([]),[se,ie]=x.useState([]),[ge,re]=x.useState([]),[Ne,$]=x.useState([]),[ve,U]=x.useState([]),[F,ce]=x.useState(""),[xe,Te]=x.useState(""),[ae,Q]=x.useState(null),[me,Z]=x.useState(""),[C,Y]=x.useState(""),[y,T]=x.useState(!1),k=x.useMemo(()=>{const H=F.trim().toLowerCase();return H?fe.filter(K=>`${K.id} ${K.name} ${K.email}`.toLowerCase().includes(H)):fe},[F,fe]);async function d(){const H=new Date().getTimezoneOffset(),[K,W,J,he,we,Ze]=await Promise.all([pe(`/api/overview?timezoneOffset=${H}`),pe("/api/users"),pe("/api/channels"),pe("/api/models"),pe("/api/logs"),pe("/api/groups")]),Ot=be(W.users),Ol=be(J.channels).map(ll),na=be(he.models).map(ii),Aa=be(we.logs),Ca=be(Ze.groups);te(K),le(Ot),ie(Ol),re(Ca),$(na),U(Aa),Te(_l=>_l&&Ot.some(rl=>rl.id===_l)?_l:Ot[0]?.id||""),Ot.length===0&&Q(null),T(!0)}async function M(H){const K=await pe(`/api/users/${H}`);Q(V0(K))}async function G(H,K){const W=await pe(`/api/users/${H}`,{method:"PATCH",body:JSON.stringify(K)});le(J=>J.map(he=>he.id===H?W.user:he)),Q(J=>J?.user.id===H?{...J,user:W.user}:J),Z("已更新用户"),window.setTimeout(()=>Z(""),1800)}async function X(H,K,W={}){const J=await pe("/api/users/bulk",{method:"POST",body:JSON.stringify({userIds:H,action:K,...W})}),he=new Map(be(J.users).map(we=>[we.id,we]));le(we=>we.map(Ze=>he.get(Ze.id)||Ze)),Q(we=>{if(!we)return we;const Ze=he.get(we.user.id);return Ze?{...we,user:Ze}:we}),Z(`已处理 ${J.updated} 个用户`),window.setTimeout(()=>Z(""),1800)}async function A(H){const K=await pe(`/api/users/${H}/api-keys`,{method:"POST",body:JSON.stringify({name:"Console Key"})});ae?.user.id===H&&Q({...ae,apiKeys:[...ae.apiKeys,K.apiKey]}),Y(K.secret),await Ss(K.secret),Z("新 Key 已创建并复制,请立即保存"),window.setTimeout(()=>Z(""),2400)}async function I(H){window.confirm("删除这个 Key?删除后使用它的请求会立即失效。")&&(await pe(`/api/api-keys/${H}`,{method:"DELETE"}),Q(K=>K&&{...K,apiKeys:K.apiKeys.filter(W=>W.id!==H)}),Z("Key 已删除"),window.setTimeout(()=>Z(""),1800))}async function oe(H,K){const W=await pe(`/api/api-keys/${H}`,{method:"PATCH",body:JSON.stringify(K)});Q(J=>J&&{...J,apiKeys:J.apiKeys.map(he=>he.id===H?W.apiKey:he)}),Z("Key 已更新"),window.setTimeout(()=>Z(""),1800)}async function Qe(H,K){const W=await pe(`/api/channels/${H}`,{method:"PATCH",body:JSON.stringify(K)});ie(J=>J.map(he=>he.id===H?ll(W.channel):he)),Pe(W.removedModels),Z("渠道已更新"),window.setTimeout(()=>Z(""),1800)}async function He(H){const K=se.find(J=>J.id===H);if(!window.confirm(`删除渠道「${K?.name||H}」?`))return;const W=await pe(`/api/channels/${H}`,{method:"DELETE"});ie(J=>J.filter(he=>he.id!==H)),Pe(W.removedModels),Z("渠道已删除"),window.setTimeout(()=>Z(""),1800)}async function dt(H){const K=await pe("/api/groups",{method:"POST",body:JSON.stringify(H)});re(W=>[...W,K.group]),Z("分组已创建"),window.setTimeout(()=>Z(""),1800)}async function V(H,K){const W=await pe(`/api/groups/${H}`,{method:"PATCH",body:JSON.stringify(K)});re(J=>J.map(he=>he.id===H?W.group:he)),Z("分组已更新"),window.setTimeout(()=>Z(""),1800)}async function Je(H){const K=ge.find(W=>W.id===H);window.confirm(`删除分组「${K?.name||H}」?删除后渠道的可见范围会移除该分组。`)&&(await pe(`/api/groups/${H}`,{method:"DELETE"}),re(W=>W.filter(J=>J.id!==H)),ie(W=>W.map(J=>({...J,allowedGroupIds:J.allowedGroupIds.filter(he=>he!==H)}))),Z("分组已删除"),window.setTimeout(()=>Z(""),1800))}async function ut(H,K){const W=be(K).map(Ot=>Ot.trim()).filter(Boolean),J=await pe(`/api/channels/${H}/sync-models`,{method:"POST",body:JSON.stringify(W.length?{models:W}:{})}),he=ll(J.channel),we=be(J.addedModels).map(ii),Ze=be(J.models);ie(Ot=>Ot.map(Ol=>Ol.id===H?he:Ol)),we.length>0&&$(Ot=>{const Ol=new Set(Ot.map(na=>na.id.toLowerCase()));return[...Ot,...we.filter(na=>!Ol.has(na.id.toLowerCase()))]}),Pe(J.removedModels),Z(W.length?`已保存 ${Ze.length} 个模型`:Ze.length?`已拉取 ${Ze.length} 个模型`:"上游没有返回模型"),window.setTimeout(()=>Z(""),2200)}function Pe(H){const K=new Set(be(H).map(W=>W.toLowerCase()));K.size!==0&&($(W=>W.filter(J=>!K.has(J.id.toLowerCase()))),Q(W=>W&&{...W,apiKeys:W.apiKeys.map(J=>({...J,allowedModels:J.allowedModels.filter(he=>!K.has(he.toLowerCase()))}))}))}async function Ft(H){try{const K=await pe(`/api/channels/${H}/check`,{method:"POST",body:JSON.stringify({})});ie(W=>W.map(J=>J.id===H?ll(K.channel):J)),Z(K.ok?`渠道可用,检测到 ${be(K.models).length} 个模型`:"渠道检测失败")}catch(K){const W=K instanceof Ns?K.payload?.channel:null;W&&ie(J=>J.map(he=>he.id===H?ll(W):he)),Z(K instanceof Error?K.message:"渠道检测失败")}window.setTimeout(()=>Z(""),2400)}async function v(H=gm("codex")){const K=await pe("/api/channels",{method:"POST",body:JSON.stringify(H)});ie(W=>[...W,ll(K.channel)]),Z("渠道已创建,可继续拉取模型或检测渠道"),window.setTimeout(()=>Z(""),2400)}async function je(H,K){const W=new FormData;W.append("file",K);const J=await $0(`/api/channels/${encodeURIComponent(H)}/import-openai-accounts`,W);ie(he=>he.map(we=>we.id===J.channel.id?ll(J.channel):we)),Z(`新增 ${J.created??J.imported} 个账号${J.updated?`,更新 ${J.updated} 个已有账号`:""}${J.skipped?`,跳过 ${J.skipped} 个`:""}`),window.setTimeout(()=>Z(""),2600)}async function $e(H,K=!1,W=""){const J=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/check`,{method:"POST",body:JSON.stringify({onlyInvalid:K,accountId:W})});ie(he=>he.map(we=>we.id===J.channel.id?ll(J.channel):we)),Z(`${K?"无效账号复检":"账号测活"}完成:${J.healthy}/${J.checked} 可用${J.failed?`,无效 ${J.failed}`:""}`),window.setTimeout(()=>Z(""),3e3)}async function Ke(H){const K=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/deduplicate`,{method:"POST",body:JSON.stringify({})});ie(W=>W.map(J=>J.id===K.channel.id?ll(K.channel):J)),Z(K.removed?`已合并 ${K.removed} 个重复账号`:"未发现可识别的重复账号"),window.setTimeout(()=>Z(""),2600)}async function il(H,K){const W=await pe(`/api/channels/${encodeURIComponent(H)}/openai-accounts/${encodeURIComponent(K)}`,{method:"DELETE"});ie(J=>J.map(he=>he.id===W.channel.id?ll(W.channel):he)),Z("账号已删除"),window.setTimeout(()=>Z(""),1800)}async function It(H){return pe(`/api/channels/${encodeURIComponent(H)}/openai-oauth/start`,{method:"POST",body:JSON.stringify({})})}async function Es(H,K){const W=await pe(`/api/channels/${encodeURIComponent(H)}/openai-oauth/complete`,{method:"POST",body:JSON.stringify(K)});return ie(J=>J.map(he=>he.id===W.channel.id?ll(W.channel):he)),Z("已通过 OAuth 添加账号"),window.setTimeout(()=>Z(""),2400),W}async function Ms(H){const K=await pe("/api/models",{method:"POST",body:JSON.stringify(H)});$(W=>[...W,ii(K.model)]),Z("模型已添加"),window.setTimeout(()=>Z(""),1800)}async function bt(H,K){const W=await pe(`/api/models/${encodeURIComponent(H)}`,{method:"PATCH",body:JSON.stringify(K)});$(J=>J.map(he=>he.id===H?ii(W.model):he)),Z("模型已更新"),window.setTimeout(()=>Z(""),1600)}async function zs(H){window.confirm(`删除模型 ${H}?渠道和 Key 中的引用也会一起清理。`)&&(await pe(`/api/models/${encodeURIComponent(H)}`,{method:"DELETE"}),$(K=>K.filter(W=>W.id!==H)),ie(K=>K.map(W=>({...W,models:W.models.filter(J=>J!==H)}))),Q(K=>K&&{...K,apiKeys:K.apiKeys.map(W=>({...W,allowedModels:W.allowedModels.filter(J=>J!==H)}))}),Z("模型已删除"),window.setTimeout(()=>Z(""),1800))}async function dn(H,K="已复制"){await Ss(H),Z(K),window.setTimeout(()=>Z(""),1600)}function la(H,K){if(H instanceof Ns&&H.status===401){T(!1),r("login"),m("auth");return}Z(K)}async function aa(){try{const H=await pe("/api/auth/status");if(R(H),!H.initialized){r("setup"),m("auth");return}if(!H.authenticated){r("login"),m("auth");return}m(H.session?.role==="admin"?"console":"account")}catch(H){la(H,"认证状态加载失败")}}async function Os(){await pe("/api/auth/logout",{method:"POST"}),window.sessionStorage.removeItem("capi-admin-token"),R(null),m("home")}return x.useEffect(()=>{let H=!1;return pe("/api/auth/status").then(K=>{H||(R(K),K.authenticated&&K.session&&m(K.session.role==="admin"?"console":"account"))}).catch(()=>{}),()=>{H=!0}},[]),x.useEffect(()=>{c==="console"&&(T(!1),d().catch(H=>la(H,"加载数据失败")))},[c]),x.useEffect(()=>{c!=="console"||!y||M(xe).catch(H=>la(H,"加载用户详情失败"))},[xe,c,y]),x.useEffect(()=>{window.localStorage.setItem("capi-theme",z)},[z]),x.useEffect(()=>{window.scrollTo({top:0,left:0})},[c,L]),c==="home"?n.jsx(fp,{theme:z,setTheme:g,enterConsole:aa}):c==="auth"?n.jsx(rp,{theme:z,mode:p,status:O,setTheme:g,setMode:r,goHome:()=>m("home"),onAuthenticated:H=>{R(K=>K?{...K,authenticated:!0,initialized:!0,session:H}:null),m(H.role==="admin"?"console":"account")}}):c==="account"?n.jsx(dp,{theme:z,setTheme:g,goHome:()=>m("home"),openLogin:aa}):n.jsxs("div",{className:"app-shell","data-theme":z,"data-density":q,children:[n.jsxs("aside",{className:"sidebar",children:[n.jsxs("div",{className:"ios-window-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsxs("div",{className:"brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"聚合网关"})]})]}),n.jsx("nav",{children:rm.map(H=>n.jsxs("button",{className:L===H.id?"nav-item active":"nav-item",onClick:()=>P(H.id),children:[n.jsx(Et,{name:H.icon}),n.jsx("span",{className:"nav-label",children:H.label})]},H.id))}),n.jsxs("div",{className:"sidebar-footer",children:[n.jsx("span",{children:"Gateway"}),n.jsxs("strong",{children:[n.jsx("span",{className:"pulse-dot"}),"Online"]})]})]}),n.jsxs("main",{className:"content",children:[n.jsxs("header",{className:"topbar",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Admin Console"}),n.jsx("h1",{children:rm.find(H=>H.id===L)?.label})]}),n.jsxs("div",{className:"topbar-actions",children:[n.jsx(qp,{value:q,options:[{value:"comfortable",label:"舒适"},{value:"compact",label:"紧凑"}],onChange:H=>_(H)}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>g(z==="dark"?"light":"dark"),children:[n.jsx(Et,{name:z==="dark"?"sun":"moon"}),n.jsx("span",{children:z==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:()=>d().catch(H=>la(H,"刷新失败")),children:"刷新"}),n.jsx("button",{className:"secondary-button home-link",onClick:()=>m("home"),children:"首页"}),n.jsx("button",{className:"secondary-button",onClick:Os,children:"退出"})]})]}),L==="overview"&&n.jsx(mp,{overview:ee,channels:se,logs:ve,onNavigate:H=>{P(H),H==="channels"&&se.length===0&&Z("渠道页可以创建第一个上游"),H==="logs"&&ve.length===0&&Z("暂无异常日志"),window.setTimeout(()=>Z(""),1800)}}),L==="users"&&n.jsx(pp,{users:k,query:F,selectedUser:ae,onQuery:ce,onSelect:Te,onUpdate:G,onBulkUpdate:X,onCreateKey:A,groups:ge,onOpenRegistration:()=>{P("settings"),Z("在账号与注册里开放注册,用户即可自助创建账号"),window.setTimeout(()=>Z(""),2400)}}),L==="groups"&&n.jsx(wp,{groups:ge,onCreate:dt,onUpdate:V,onDelete:Je}),L==="keys"&&n.jsx(vp,{selectedUser:ae,onCreateKey:A,onUpdateKey:oe,onDeleteKey:I}),L==="models"&&n.jsx(bp,{models:Ne,onCopy:dn,onCreate:Ms,onUpdate:bt,onDelete:zs}),L==="drawing"&&n.jsx(jp,{channels:se,onCreate:v,onImport:je,onCheckAccounts:$e,onDeduplicateAccounts:Ke,onDeleteAccount:il,onUpdate:Qe,onStartOAuth:It,onCompleteOAuth:Es}),L==="channels"&&n.jsx(_p,{channels:se,groups:ge,onUpdate:Qe,onCreate:v,onImport:je,onDelete:He,onSyncModels:ut,onCheck:Ft}),L==="logs"&&n.jsx(Up,{logs:ve,onCopy:dn}),L==="settings"&&n.jsx(Hp,{models:Ne,channels:se})]}),C&&n.jsx("div",{className:"secret-dialog-backdrop",role:"presentation",children:n.jsxs("section",{className:"secret-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"secret-dialog-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"One-time secret"}),n.jsx("h2",{id:"secret-dialog-title",children:"完整 API Key"})]}),n.jsx("p",{children:"完整密钥只显示这一次。列表中的星号内容只是识别前缀,不能用于 API 调用。"}),n.jsx("code",{children:C}),n.jsxs("div",{className:"secret-dialog-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>{Ss(C),Z("完整 Key 已复制"),window.setTimeout(()=>Z(""),1800)},children:"复制"}),n.jsx("button",{className:"primary-button",onClick:()=>Y(""),children:"完成"})]})]})}),me&&n.jsx("div",{className:"toast",children:me})]})}function rp({theme:c,mode:m,status:p,setTheme:r,setMode:O,goHome:R,onAuthenticated:L}){const[P,z]=x.useState(""),[g,q]=x.useState(""),[_,ee]=x.useState(""),[te,fe]=x.useState(""),[le,se]=x.useState(""),[ie,ge]=x.useState(""),[re,Ne]=x.useState(!1),[$,ve]=x.useState("username"),[U,F]=x.useState("0"),[ce,xe]=x.useState(""),[Te,ae]=x.useState(!1),Q=m==="setup",me=m==="register",Z=Ts(p?.registrationMode),C=me&&Z==="email",Y=me&&Z==="discord";async function y(){if(!Y){if((Q||me)&&le!==ie){xe("两次输入的密码不一致");return}ae(!0),xe("");try{const T=Q?"/api/auth/setup":me?"/api/auth/register":"/api/auth/login",k=C?cp(_):P,d=m==="login"?{identifier:P,password:le}:{username:k,password:le,displayName:g,email:_,discordUserId:Q?te:"",registrationEnabled:Q?re:void 0,registrationMode:Q?$:void 0,defaultBalance:Q?Number(U||0):void 0},M=await pe(T,{method:"POST",body:JSON.stringify(d)});L(M.session)}catch(T){xe(T instanceof Error?T.message:"操作失败")}finally{ae(!1)}}}return n.jsxs("main",{className:"auth-page","data-theme":c,children:[n.jsxs("header",{className:"auth-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:R,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>r(c==="dark"?"light":"dark"),children:[n.jsx(Et,{name:c==="dark"?"sun":"moon"}),n.jsx("span",{children:c==="dark"?"浅色":"暗色"})]})]}),n.jsxs("section",{className:"auth-stage",children:[n.jsxs("div",{className:"auth-intro",children:[n.jsx("span",{children:Q?"First Run":"Welcome Back"}),n.jsx("h1",{children:Q?"初始化 CAPI":me?"创建账号":"登录"}),n.jsx("p",{children:Q?"创建第一个管理员账号,完成后即可进入控制台。":"使用你的 CAPI 账号继续。"})]}),n.jsxs("form",{className:"auth-form",onSubmit:T=>{T.preventDefault(),y()},children:[Y?n.jsxs("div",{className:"auth-discord-register",children:[n.jsx("strong",{children:"使用 Discord 创建账号"}),n.jsx("span",{children:"继续后会按站点设置校验服务器和身份组。"}),p?.discordEnabled?n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"继续使用 Discord"}):n.jsx("div",{className:"auth-message",children:"管理员还没有启用 Discord 登录"})]}):n.jsxs(n.Fragment,{children:[m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:g,onChange:T=>q(T.target.value),autoComplete:"name",placeholder:"CAPI"})]}),!C&&n.jsxs("label",{children:[n.jsx("span",{children:m==="login"?"账号或邮箱":"账号"}),n.jsx("input",{value:P,onChange:T=>z(T.target.value),autoComplete:"username",placeholder:m==="login"?"输入账号或邮箱":"3-32 位字母、数字、_ 或 -"})]}),(Q||C)&&n.jsxs("label",{children:[n.jsx("span",{children:C?"邮箱":"邮箱(可选)"}),n.jsx("input",{type:"email",value:_,onChange:T=>ee(T.target.value),autoComplete:"email",placeholder:"name@example.com"})]}),Q&&n.jsxs(n.Fragment,{children:[n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:te,onChange:T=>fe(T.target.value),placeholder:"绑定管理员 Discord 账号"})]}),n.jsxs("div",{className:"setup-options",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放注册"}),n.jsx("button",{type:"button",className:re?"ios-switch is-on":"ios-switch","aria-pressed":re,onClick:()=>Ne(T=>!T),children:n.jsx("span",{})})]}),n.jsxs("label",{children:[n.jsx("span",{children:"注册方式"}),n.jsxs("select",{value:$,onChange:T=>ve(Ts(T.target.value)),children:[n.jsx("option",{value:"username",children:"账号密码"}),n.jsx("option",{value:"email",children:"邮箱"}),n.jsx("option",{value:"discord",children:"Discord"})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新用户初始额度"}),n.jsx("input",{type:"number",min:"0",step:"0.01",value:U,onChange:T=>F(T.target.value)})]})]})]}),n.jsxs("label",{children:[n.jsx("span",{children:"密码"}),n.jsx("input",{type:"password",value:le,onChange:T=>se(T.target.value),autoComplete:m==="login"?"current-password":"new-password",placeholder:"至少 8 个字符"})]}),m!=="login"&&n.jsxs("label",{children:[n.jsx("span",{children:"确认密码"}),n.jsx("input",{type:"password",value:ie,onChange:T=>ge(T.target.value),autoComplete:"new-password",placeholder:"再次输入密码"})]}),n.jsx("div",{className:"auth-message",role:"status",children:ce}),n.jsx("button",{className:"primary-button auth-submit",type:"submit",disabled:Te,children:Te?"请稍候":Q?"创建管理员":me?"注册":"登录"})]}),!Q&&!Y&&p?.discordEnabled&&n.jsx("a",{className:"discord-login-button",href:"/api/auth/discord/start",children:"使用 Discord 登录"}),!Q&&n.jsx("div",{className:"auth-switch",children:m==="login"&&p?.registrationEnabled?n.jsx("button",{type:"button",onClick:()=>O("register"),children:"创建账号"}):n.jsx("button",{type:"button",onClick:()=>O("login"),children:"返回登录"})})]})]})]})}function dp({theme:c,setTheme:m,goHome:p,openLogin:r}){const[O,R]=x.useState(null),[L,P]=x.useState([]),[z,g]=x.useState(null),[q,_]=x.useState(!1),[ee,te]=x.useState(""),[fe,le]=x.useState(""),[se,ie]=x.useState("");async function ge(){try{const[U,F,ce]=await Promise.all([pe("/api/account/me"),pe("/api/catalog/models"),pe("/api/account/check-in")]);R({...U,apiKeys:be(U.apiKeys)}),P(be(F.models).map(ii)),g(ce.checkIn)}catch{r()}}x.useEffect(()=>{ge()},[]);async function re(){if(!(!z?.enabled||z.claimed||q)){_(!0),te("");try{const U=await pe("/api/account/check-in",{method:"POST",body:JSON.stringify({})});R(F=>F&&{...F,user:U.user}),g(U.checkIn),te(`签到成功,获得 ${U.reward.toFixed(2)} 额度`)}catch(U){te(U instanceof Error?U.message:"签到失败,请稍后重试")}finally{_(!1)}}}async function Ne(){try{const U=await pe("/api/account/api-keys",{method:"POST",body:JSON.stringify({name:"My API Key"})});le(U.secret),ie("新密钥只显示这一次"),await ge()}catch(U){ie(U instanceof Error?U.message:"创建密钥失败")}}async function $(U){if(window.confirm("删除这个 API Key?使用它的请求会立即失效。"))try{await pe(`/api/account/api-keys/${U}`,{method:"DELETE"}),R(F=>F&&{...F,apiKeys:F.apiKeys.filter(ce=>ce.id!==U)}),ie("密钥已删除")}catch(F){ie(F instanceof Error?F.message:"删除密钥失败")}}async function ve(){await pe("/api/auth/logout",{method:"POST"}),p()}return n.jsxs("main",{className:"account-page","data-theme":c,children:[n.jsxs("header",{className:"account-topbar",children:[n.jsxs("button",{className:"auth-brand",onClick:p,children:[n.jsx("span",{className:"brand-mark",children:"C"}),n.jsx("strong",{children:"CAPI"})]}),n.jsxs("div",{className:"account-actions",children:[n.jsx("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(c==="dark"?"light":"dark"),children:n.jsx(Et,{name:c==="dark"?"sun":"moon"})}),n.jsx("button",{className:"secondary-button",onClick:ve,children:"退出"})]})]}),n.jsxs("section",{className:"account-content",children:[n.jsxs("div",{className:"account-heading",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"My CAPI"}),n.jsx("h1",{children:O?.user.name||"账户"})]}),n.jsxs("div",{className:"account-balance",children:[n.jsx("span",{children:"余额"}),n.jsx("strong",{children:O?O.user.balance.toFixed(2):"-"})]})]}),n.jsxs("section",{className:"account-section check-in-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Daily Reward"}),n.jsx("h2",{children:"每日签到"})]}),n.jsx("button",{className:"primary-button",disabled:!z?.enabled||!!z?.claimed||q,onClick:re,children:q?"领取中":z?.claimed?"今日已签到":z?.enabled?"签到领额度":"暂未开放"})]}),n.jsxs("div",{className:"check-in-summary",children:[n.jsxs("div",{children:[n.jsx("span",{children:"今日状态"}),n.jsx("strong",{children:z?.claimed?`已领取 ${z.reward.toFixed(2)}`:z?.enabled?"等待签到":"活动关闭"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"随机奖励"}),n.jsx("strong",{children:z?`${z.minReward.toFixed(2)} - ${z.maxReward.toFixed(2)}`:"-"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"结算日期"}),n.jsx("strong",{children:z?.day||"北京时间"})]})]}),n.jsx("p",{className:"check-in-note",children:"每天按北京时间 00:00 刷新,奖励领取后直接计入账户余额。"}),ee&&n.jsx("p",{className:"account-message check-in-message",role:"status",children:ee})]}),n.jsxs("section",{className:"account-section",children:[n.jsxs("div",{className:"account-section-title",children:[n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"API Keys"}),n.jsx("h2",{children:"API 密钥"})]}),n.jsx("button",{className:"primary-button",onClick:Ne,children:"创建密钥"})]}),fe&&n.jsx("code",{className:"one-time-secret",children:fe}),se&&n.jsx("p",{className:"account-message",children:se}),n.jsxs("div",{className:"account-key-list",children:[O?.apiKeys?.map(U=>n.jsxs("div",{className:"account-key-item",children:[n.jsx("span",{className:"account-key-mark","aria-hidden":"true",children:n.jsx(Et,{name:"key"})}),n.jsxs("div",{className:"account-key-info",children:[n.jsx("strong",{children:U.name}),n.jsxs("code",{children:[U.prefix,"…"]})]}),n.jsx(zt,{tone:U.status,children:Mt(U.status)}),n.jsx("button",{className:"icon-button","aria-label":`删除 ${U.name}`,title:"删除密钥",onClick:()=>$(U.id),children:n.jsx(Et,{name:"ban"})})]},U.id)),be(O?.apiKeys).length===0&&n.jsx("div",{className:"empty",children:"还没有 API 密钥"})]})]}),n.jsxs("section",{className:"account-section",children:[n.jsx("div",{className:"account-section-title",children:n.jsxs("div",{children:[n.jsx("p",{className:"eyebrow",children:"Models"}),n.jsx("h2",{children:"可用模型"})]})}),n.jsxs("div",{className:"account-model-grid",children:[L.map(U=>n.jsxs("article",{children:[n.jsx("span",{children:U.vendor}),n.jsx("strong",{children:U.name}),n.jsx("p",{children:U.description}),n.jsx("code",{children:U.id})]},U.id)),L.length===0&&n.jsx("div",{className:"account-model-empty",children:"暂无可用模型,管理员配置渠道后将在此展示"})]})]})]})]})}function fp({theme:c,setTheme:m,enterConsole:p}){return n.jsxs("main",{className:"public-home","data-theme":c,children:[n.jsxs("header",{className:"home-topbar",children:[n.jsxs("div",{className:"home-brand",children:[n.jsx("div",{className:"brand-mark",children:"C"}),n.jsxs("div",{children:[n.jsx("strong",{children:"CAPI"}),n.jsx("span",{children:"AI 聚合网关"})]})]}),n.jsxs("div",{className:"home-actions",children:[n.jsxs("button",{className:"theme-toggle","aria-label":"切换暗色模式",onClick:()=>m(c==="dark"?"light":"dark"),children:[n.jsx(Et,{name:c==="dark"?"sun":"moon"}),n.jsx("span",{children:c==="dark"?"浅色":"暗色"})]}),n.jsx("button",{className:"primary-button",onClick:p,children:"控制台"})]})]}),n.jsxs("section",{className:"home-hero",children:[n.jsxs("div",{className:"home-copy",children:[n.jsx("span",{className:"home-kicker",children:"兼容 OpenAI 格式的网关"}),n.jsxs("h1",{children:["CAPI",n.jsx("span",{children:"轻量 AI 聚合网关"})]}),n.jsx("p",{children:"面向个人用户和团队的模型接入层。把 API Key、额度、模型渠道和调用日志放在一个清爽控制台里,保持轻量,也便于排障。"}),n.jsx("div",{className:"home-cta",children:n.jsx("button",{className:"primary-button",onClick:p,children:"进入控制台"})}),n.jsxs("div",{className:"integration-row","aria-label":"网关能力概览",children:[n.jsx("span",{children:"网关能力"}),n.jsxs("div",{children:[n.jsx("span",{children:"OpenAI 兼容接口"}),n.jsx("span",{children:"额度控制"}),n.jsx("span",{children:"调用审计"})]})]})]}),n.jsxs("div",{className:"gateway-terminal","aria-label":"CAPI 终端请求示意",children:[n.jsxs("div",{className:"terminal-titlebar",children:[n.jsxs("div",{className:"terminal-dots","aria-hidden":"true",children:[n.jsx("span",{}),n.jsx("span",{}),n.jsx("span",{})]}),n.jsx("strong",{children:"CAPI Terminal"}),n.jsxs("div",{className:"terminal-status",children:[n.jsx("span",{className:"pulse-dot"}),n.jsx("strong",{children:"Online"})]})]}),n.jsxs("div",{className:"terminal-endpoint",children:[n.jsx("span",{children:"POST"}),n.jsx("strong",{children:"/v1/chat/completions"})]}),n.jsxs("div",{className:"terminal-body",children:[n.jsxs("div",{className:"terminal-block",children:[n.jsx("span",{children:"REQUEST"}),n.jsx("pre",{children:`curl https://api.capi.local/v1/chat/completions \\ - -H "Authorization: Bearer cat_..." \\ - -d '{ - "model": "capi-fast", - "messages": [{ "role": "user", "content": "ping" }] - }'`})]}),n.jsxs("div",{className:"terminal-route",children:[n.jsxs("div",{children:[n.jsx("span",{children:"auth"}),n.jsx("strong",{children:"pass"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"quota"}),n.jsx("strong",{children:"ok"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"route"}),n.jsx("strong",{children:"capi-fast"})]}),n.jsxs("div",{children:[n.jsx("span",{children:"latency"}),n.jsx("strong",{children:"186ms"})]})]}),n.jsxs("div",{className:"terminal-block response",children:[n.jsx("span",{children:"RESPONSE"}),n.jsxs("pre",{children:[`{ - "status": 200, - "model": "capi-fast", - "usage": { "total_tokens": 27 }, - "message": "request routed" -}`,n.jsx("span",{className:"terminal-caret","aria-hidden":"true"})]})]})]})]})]})]})}function mp({overview:c,channels:m,logs:p,onNavigate:r}){const O=p.filter(R=>R.status!=="success");return n.jsxs("section",{className:"page-stack",children:[n.jsxs("div",{className:"hero-strip",children:[n.jsxs("div",{children:[n.jsx("span",{children:"Live Gateway"}),n.jsxs("strong",{children:["CAPI 网关正在服务 ",c?.activeUsers??"-"," 个活跃用户"]}),n.jsx("p",{children:"请求进入 CAPI 后,会按额度、模型和渠道状态自动选择最合适的上游。"})]}),n.jsxs("div",{className:"live-island",children:[n.jsx("div",{className:"pulse-dot"}),n.jsx("span",{children:"在线"})]})]}),n.jsxs("div",{className:"quick-actions","aria-label":"快捷操作",children:[n.jsx(xs,{icon:"key",label:"创建 Key",onClick:()=>r("keys")}),n.jsx(xs,{icon:"route",label:"配置渠道",onClick:()=>r("channels")}),n.jsx(xs,{icon:"users",label:"调整额度",onClick:()=>r("users")}),n.jsx(xs,{icon:"logs",label:"查看异常",onClick:()=>r("logs")})]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(nl,{label:"活跃用户",value:c?Na(c.activeUsers):"-"}),n.jsx(nl,{label:"今日请求",value:c?Na(c.requestsToday):"-"}),n.jsx(nl,{label:"今日输入",value:c?Na(c.todayInputTokens):"-"}),n.jsx(nl,{label:"今日输出",value:c?Na(c.todayOutputTokens):"-"}),n.jsx(nl,{label:"今日扣费",value:c?si(c.todayCost,4):"-"}),n.jsx(nl,{label:"账户余额",value:c?si(c.totalBalance):"-"}),n.jsx(nl,{label:"成功率",value:c?`${c.successRate}%`:"-"})]}),n.jsx(hp,{}),n.jsxs("div",{className:"split-grid",children:[n.jsx(lt,{title:"渠道状态",children:m.length?m.map(R=>n.jsxs("div",{className:"list-row overview-channel-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:R.name}),n.jsx("span",{title:be(R.models).join(", "),children:ip(R.models)})]}),n.jsx(zt,{tone:R.status,children:Mt(R.status)})]},R.id)):n.jsx(qt,{text:"暂无渠道"})}),n.jsx(lt,{title:"最近请求",children:p.length?p.slice(0,4).map(R=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:to(R)}),n.jsxs("span",{children:[R.id," · ",R.errorCode||Wt(R.createdAt)]})]}),n.jsx(zt,{tone:R.status,children:Mt(R.status)})]},R.id)):n.jsx(qt,{text:O.length?"暂无最近请求":"暂无请求"})})]})]})}function xs({icon:c,label:m,onClick:p}){return n.jsxs("button",{className:"quick-action",onClick:p,children:[n.jsx(Et,{name:c}),n.jsx("span",{children:m})]})}function hp(){const c=[{label:"认证",detail:"校验 API Key"},{label:"额度",detail:"检查余额"},{label:"路由",detail:"选择渠道"},{label:"响应",detail:"返回结果"}];return n.jsxs("section",{className:"flow-panel","aria-label":"网关流转",children:[n.jsxs("div",{className:"flow-copy",children:[n.jsx("span",{children:"Request Flow"}),n.jsx("strong",{children:"请求处理流程"})]}),n.jsx("div",{className:"flow-steps",children:c.map((m,p)=>n.jsxs("div",{className:"flow-step",children:[n.jsx("div",{className:"flow-index",children:p+1}),n.jsx("strong",{children:m.label}),n.jsx("span",{children:m.detail})]},m.label))})]})}function pp({users:c,query:m,selectedUser:p,onQuery:r,onSelect:O,onUpdate:R,onBulkUpdate:L,onCreateKey:P,groups:z,onOpenRegistration:g}){const[_,ee]=x.useState(1),[te,fe]=x.useState("all"),[le,se]=x.useState(new Set),[ie,ge]=x.useState("10"),[re,Ne]=x.useState(""),[$,ve]=x.useState(!1),[U,F]=x.useState("10"),[ce,xe]=x.useState(""),[Te,ae]=x.useState(""),[Q,me]=x.useState(!1),Z=te==="all"?c:c.filter(A=>A.status===te),C=Z.filter(A=>A.role!=="admin"),Y=Math.max(1,Math.ceil(Z.length/25)),y=Math.min(_,Y),T=Z.slice((y-1)*25,y*25),k=C.length>0&&C.every(A=>le.has(A.id));x.useEffect(()=>{ee(1)},[m,te]),x.useEffect(()=>{const A=new Set(c.map(I=>I.id));se(I=>new Set([...I].filter(oe=>A.has(oe))))},[c]),x.useEffect(()=>{F("10"),xe(""),ae("")},[p?.user.id]);function d(A){se(I=>{const oe=new Set(I);return oe.has(A)?oe.delete(A):oe.add(A),oe})}function M(){se(A=>{const I=new Set(A);return k?C.forEach(oe=>I.delete(oe.id)):C.forEach(oe=>I.add(oe.id)),I})}async function G(A,I){if(le.size!==0){ve(!0);try{await L([...le],A,I),se(new Set),Ne("")}finally{ve(!1)}}}async function X(A){if(!p)return;const I=Math.abs(Number(U));if(!Number.isFinite(I)||I<=0){ae("请输入大于 0 的金额");return}me(!0),ae("");try{await L([p.user.id],"adjust_balance",{amount:Number((I*A).toFixed(4)),reason:ce.trim()||(A>0?"管理员增加额度":"管理员扣减额度")}),ae(A>0?"额度已增加":"额度已扣减"),xe("")}catch(oe){ae(oe instanceof Error?oe.message:"额度调整失败")}finally{me(!1)}}return n.jsxs("section",{className:"users-layout",children:[n.jsxs(lt,{title:"用户管理",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Et,{name:"search"}),n.jsx("input",{value:m,onChange:A=>r(A.target.value),placeholder:"搜索 ID、姓名或邮箱"})]}),n.jsx("button",{className:"icon-button",title:"开放注册",onClick:g,children:n.jsx(Et,{name:"plus"})})]}),n.jsxs("div",{className:"user-summary-strip",children:[n.jsxs("span",{children:[n.jsx("strong",{children:c.length})," 匹配用户"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.filter(A=>A.status==="active").length})," 正常"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.filter(A=>A.status==="disabled").length})," 禁用"]}),n.jsxs("span",{children:[n.jsx("strong",{children:c.reduce((A,I)=>A+I.requestsToday,0)})," 今日请求"]})]}),n.jsx("div",{className:"user-filter-row",role:"group","aria-label":"用户状态筛选",children:[{value:"all",label:"全部"},{value:"active",label:"正常"},{value:"limited",label:"受限"},{value:"disabled",label:"禁用"}].map(A=>n.jsx("button",{type:"button",className:te===A.value?"selected":"",onClick:()=>fe(A.value),children:A.label},A.value))}),n.jsx("button",{type:"button",className:"secondary-button mobile-bulk-select",onClick:M,children:k?"取消全选":`全选结果(${C.length})`}),le.size>0&&n.jsxs("div",{className:"bulk-action-bar",children:[n.jsxs("strong",{children:["已选 ",le.size," 人"]}),n.jsx("input",{type:"number",step:"0.01",value:ie,onChange:A=>ge(A.target.value),"aria-label":"额度调整值"}),n.jsx("input",{value:re,onChange:A=>Ne(A.target.value),placeholder:"原因,例如:活动赠送","aria-label":"调整原因"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:$||!Number(ie),onClick:()=>G("adjust_balance",{amount:Number(ie),reason:re}),children:"调整额度"}),n.jsx("button",{type:"button",className:"secondary-button",disabled:$,onClick:()=>G("set_status",{value:"active"}),children:"启用"}),n.jsx("button",{type:"button",className:"danger-button",disabled:$,onClick:()=>G("set_status",{value:"disabled"}),children:"禁用"})]}),n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head users-table",children:[n.jsx("input",{type:"checkbox",checked:k,onChange:M,"aria-label":"选择当前筛选结果"}),n.jsx("span",{children:"用户"}),n.jsx("span",{children:"状态"}),n.jsx("span",{children:"余额"}),n.jsx("span",{children:"今日"})]}),T.map(A=>n.jsxs("div",{className:p?.user.id===A.id?"table-row users-table selected":"table-row users-table",role:"button",tabIndex:0,onClick:()=>O(A.id),onKeyDown:I=>{(I.key==="Enter"||I.key===" ")&&O(A.id)},children:[n.jsx("input",{type:"checkbox",checked:le.has(A.id),disabled:A.role==="admin",onChange:()=>d(A.id),onClick:I=>I.stopPropagation(),"aria-label":A.role==="admin"?`${A.name} 是管理员,不参与批量操作`:`选择 ${A.name}`}),n.jsxs("span",{children:[n.jsx("strong",{children:A.name}),n.jsxs("small",{children:[A.id," · ",A.email||"未绑定邮箱"]})]}),n.jsx(zt,{tone:A.status,children:Mt(A.status)}),n.jsx("span",{children:si(A.balance)}),n.jsx("span",{children:A.requestsToday})]},A.id)),Z.length===0&&n.jsx(qt,{text:"暂无匹配用户"})]}),Z.length>25&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:y<=1,onClick:()=>ee(A=>Math.max(1,A-1)),children:"上一页"}),n.jsxs("span",{children:[y," / ",Y]}),n.jsx("button",{className:"secondary-button",disabled:y>=Y,onClick:()=>ee(A=>Math.min(Y,A+1)),children:"下一页"})]})]}),n.jsx(lt,{title:"用户详情",children:p?n.jsxs("div",{className:"detail-stack",children:[n.jsxs("div",{className:"user-hero",children:[n.jsx("div",{className:"avatar",children:p.user.name.slice(0,1)}),n.jsxs("div",{children:[n.jsx("h2",{children:p.user.name}),n.jsx("p",{children:p.user.email})]}),n.jsx(zt,{tone:p.user.status,children:Mt(p.user.status)})]}),n.jsxs("div",{className:"settings-group",children:[n.jsx($t,{label:"角色",value:p.user.role==="admin"?"管理员":"用户"}),n.jsx($t,{label:"余额",value:si(p.user.balance)}),n.jsx($t,{label:"总请求",value:String(p.user.totalRequests)}),n.jsx($t,{label:"最后登录",value:Wt(p.user.lastLoginAt)}),n.jsx($t,{label:"API 调用",value:p.user.status==="disabled"?"关闭":"允许",switchOn:p.user.status!=="disabled"})]}),n.jsxs("div",{className:"group-assign-row",children:[n.jsxs("label",{children:[n.jsx("span",{children:"所属分组"}),n.jsxs("select",{value:p.user.groupId||"",onChange:A=>R(p.user.id,{groupId:A.target.value}),children:[n.jsx("option",{value:"",children:"未分组"}),z.map(A=>n.jsx("option",{value:A.id,children:A.name},A.id))]})]}),n.jsx("small",{children:"分组决定该用户可路由到哪些渠道;未分组用户只能使用未限制分组的渠道。"})]}),n.jsxs("div",{className:"balance-adjuster",children:[n.jsxs("div",{className:"balance-adjuster-title",children:[n.jsx("strong",{children:"调整余额"}),n.jsxs("span",{children:["当前 ",si(p.user.balance)]})]}),n.jsxs("div",{className:"balance-adjuster-fields",children:[n.jsxs("label",{children:[n.jsx("span",{children:"金额"}),n.jsx("input",{type:"number",min:"0.0001",step:"0.01",value:U,onChange:A=>F(A.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"备注"}),n.jsx("input",{value:ce,onChange:A=>xe(A.target.value),placeholder:"可选,会记录到流水"})]})]}),n.jsxs("div",{className:"balance-adjuster-actions",children:[n.jsx("button",{className:"secondary-button",disabled:Q,onClick:()=>X(1),children:"增加"}),n.jsx("button",{className:"danger-button",disabled:Q,onClick:()=>X(-1),children:"扣减"}),n.jsx("span",{role:"status",children:Te})]})]}),n.jsxs("div",{className:"action-row",children:[n.jsx("button",{className:"secondary-button",onClick:()=>P(p.user.id),children:"创建 Key"}),n.jsx("button",{className:"secondary-button",disabled:p.user.role==="admin",onClick:()=>R(p.user.id,{status:p.user.status==="disabled"?"active":"disabled"}),children:p.user.role==="admin"?"管理员保护":p.user.status==="disabled"?"解封":"禁用"})]}),n.jsxs("div",{children:[n.jsx("h3",{children:"API Key"}),p.apiKeys.map(A=>n.jsxs("div",{className:"list-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:A.name}),n.jsxs("span",{children:[A.prefix,"*** · ",A.requestCount," 次"]})]}),n.jsx(zt,{tone:A.status,children:Mt(A.status)})]},A.id)),p.apiKeys.length===0&&n.jsx(qt,{text:"暂无 API Key"})]})]}):n.jsx(qt,{text:"请选择一个用户"})})]})}function vp({selectedUser:c,onCreateKey:m,onUpdateKey:p,onDeleteKey:r}){return n.jsx(lt,{title:"密钥管理",children:c?n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsxs("span",{className:"muted-inline",children:[c.user.name," · 完整 Key 只在创建时显示,丢失请重新创建"]}),n.jsx("button",{className:"primary-button",onClick:()=>m(c.user.id),children:"创建 Key"})]}),c.apiKeys.length?c.apiKeys.map(O=>n.jsx(yp,{apiKey:O,onSave:p,onDelete:r},O.id)):n.jsx(qt,{text:"暂无密钥"})]}):n.jsx(qt,{text:"请选择一个用户"})})}function yp({apiKey:c,onSave:m,onDelete:p}){const[r,O]=x.useState(c.name),[R,L]=x.useState(be(c.allowedModels).join(", ")),[P,z]=x.useState(fm(c.expiresAt||"")),[g,q]=x.useState(String(c.rateLimitPerMinute||"")),[_,ee]=x.useState(!1),te=be(c.allowedModels).length?be(c.allowedModels).join(", "):"全部模型";x.useEffect(()=>{O(c.name),L(be(c.allowedModels).join(", ")),z(fm(c.expiresAt||"")),q(String(c.rateLimitPerMinute||""))},[c]);async function fe(){ee(!0);try{await m(c.id,{name:r.trim()||"API Key",allowedModels:Ic(R),expiresAt:tp(P),rateLimitPerMinute:Number(g||0)})}finally{ee(!1)}}return n.jsxs("details",{className:"key-editor key-editor-collapsible",children:[n.jsxs("summary",{className:"key-editor-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:c.name}),n.jsxs("span",{children:[c.prefix,"*** · ",te," · 最后使用 ",Wt(c.lastUsedAt)]})]}),n.jsxs("div",{className:"row-actions",children:[n.jsx(zt,{tone:c.status,children:Mt(c.status)}),n.jsx("span",{className:"key-expand-hint",children:"管理"})]})]}),n.jsxs("div",{className:"key-editor-body",children:[n.jsxs("div",{className:"key-editor-grid",children:[n.jsxs("label",{children:["名称",n.jsx("input",{value:r,onChange:le=>O(le.target.value)})]}),n.jsxs("label",{children:["允许模型",n.jsx("input",{value:R,onChange:le=>L(le.target.value),placeholder:"留空表示全部模型,多个用逗号分隔"})]}),n.jsxs("label",{children:["过期时间",n.jsx("input",{type:"datetime-local",value:P,onChange:le=>z(le.target.value)})]}),n.jsxs("label",{children:["每分钟限制",n.jsx("input",{type:"number",min:"0",value:g,onChange:le=>q(le.target.value),placeholder:"0 使用全局限制"})]})]}),n.jsxs("div",{className:"key-editor-actions",children:[n.jsx("button",{className:"secondary-button",onClick:()=>m(c.id,{status:c.status==="active"?"disabled":"active"}),children:c.status==="active"?"停用密钥":"启用密钥"}),n.jsx("button",{className:"danger-button",onClick:()=>p(c.id),children:"删除密钥"}),n.jsx("button",{className:"primary-button",disabled:_,onClick:fe,children:_?"保存中":"保存设置"})]})]})]})}function bp({models:c,onCopy:m,onCreate:p,onUpdate:r,onDelete:O}){const R=c.filter(y=>y.recommended),[L,P]=x.useState(""),[z,g]=x.useState("all"),[q,_]=x.useState("all"),[ee,te]=x.useState(1),[fe,le]=x.useState(""),[se,ie]=x.useState(""),[ge,re]=x.useState(""),[Ne,$]=x.useState(""),[ve,U]=x.useState(""),[F,ce]=x.useState(""),xe=60,Te=x.useMemo(()=>{const y=new Map;return c.forEach(T=>{const k=$c(T);y.set(k,(y.get(k)||0)+1)}),Array.from(y.entries()).sort((T,k)=>k[1]-T[1]||al(T[0]).localeCompare(al(k[0]))).map(([T,k])=>({provider:T,count:k}))},[c]),ae=x.useMemo(()=>{const y=L.trim().toLowerCase();return c.filter(T=>z!=="all"&&$c(T)!==z||q!=="all"&&T.status!==q?!1:y?[T.id,T.name,T.vendor,T.category,T.description,...be(T.aliases)].join(" ").toLowerCase().includes(y):!0)},[c,L,z,q]),Q=x.useMemo(()=>{const y=new Map;ae.forEach(G=>{const X=$c(G);y.set(X,[...y.get(X)||[],G])});const T=[];let k=[],d=0;const M=Array.from(y.entries()).sort((G,X)=>al(G[0]).localeCompare(al(X[0])));for(const G of M)k.length>0&&d+G[1].length>xe&&(T.push(k),k=[],d=0),k.push(G),d+=G[1].length;return k.length>0&&T.push(k),T},[ae]),me=Math.max(1,Q.length),Z=Math.min(ee,me),C=Q[Z-1]||[];x.useEffect(()=>{te(1)},[L,z,q,c.length]);async function Y(y){y.preventDefault();const T=fe.trim();if(T){ce("");try{await p({id:T,name:se.trim()||T,vendor:ge.trim()||"Custom",aliases:Ne.split(",").map(k=>k.trim()).filter(Boolean),category:"通用",description:ve.trim(),price:"自定义",context:"未配置上下文"}),le(""),ie(""),re(""),$(""),U("")}catch(k){ce(k instanceof Error?k.message:"模型添加失败")}}}return n.jsxs("section",{className:"models-page",children:[n.jsx("div",{className:"model-hero",children:n.jsxs("div",{children:[n.jsx("span",{children:"Model Catalog"}),n.jsx("strong",{children:"Models"})]})}),n.jsx(lt,{title:"新增模型",children:n.jsxs("form",{className:"model-create-form",onSubmit:Y,children:[n.jsx("input",{value:fe,onChange:y=>le(y.target.value),placeholder:"模型 ID,例如 openai/gpt-4.1"}),n.jsx("input",{value:se,onChange:y=>ie(y.target.value),placeholder:"显示名称(可选)"}),n.jsx("input",{value:ge,onChange:y=>re(y.target.value),placeholder:"供应商(可选)"}),n.jsx("input",{value:Ne,onChange:y=>$(y.target.value),placeholder:"代称,多个用逗号分隔(可选)"}),n.jsx("input",{className:"model-create-wide",value:ve,onChange:y=>U(y.target.value),placeholder:"描述(可选)"}),n.jsx("button",{className:"primary-button",type:"submit",children:"新增模型"}),n.jsx("div",{className:"model-create-message",role:"status",children:F})]})}),R.length>0&&n.jsx(lt,{title:"推荐模型",children:n.jsx("div",{className:"model-grid",children:R.map(y=>n.jsx(xp,{model:y,featured:!0,onCopy:m,onUpdate:r},y.id))})}),n.jsxs(lt,{title:"全部模型",children:[n.jsxs("div",{className:"panel-toolbar model-list-toolbar",children:[n.jsx("input",{value:L,onChange:y=>P(y.target.value),placeholder:"搜索模型 ID、名称、供应商或代称"}),n.jsx("div",{className:"model-filter-actions",children:[{value:"all",label:"全部"},{value:"available",label:"可用"},{value:"disabled",label:"禁用"}].map(y=>n.jsx("button",{type:"button",className:q===y.value?"selected":"",onClick:()=>_(y.value),children:y.label},y.value))})]}),n.jsxs("div",{className:"model-provider-filter","aria-label":"按供应商筛选模型",children:[n.jsxs("button",{type:"button",className:z==="all"?"selected":"",onClick:()=>g("all"),children:[n.jsx("span",{className:"provider-icon provider-icon-all","aria-hidden":"true",children:"All"}),n.jsx("strong",{children:"全部"}),n.jsx("small",{children:c.length})]}),Te.map(y=>n.jsxs("button",{type:"button",className:z===y.provider?"selected":"",onClick:()=>g(y.provider),children:[n.jsx(mm,{provider:y.provider}),n.jsx("strong",{children:al(y.provider)}),n.jsx("small",{children:y.count})]},y.provider))]}),n.jsxs("div",{className:"model-list-summary",children:[n.jsx("span",{children:z==="all"?"全部供应商":al(z)}),n.jsx("strong",{children:ae.length}),n.jsx("span",{children:"个模型"})]}),ae.length>0?n.jsxs(n.Fragment,{children:[n.jsx("div",{className:"model-provider-groups",children:C.map(([y,T])=>n.jsxs("section",{className:"model-provider-group",children:[n.jsxs("header",{children:[n.jsx(mm,{provider:y}),n.jsxs("div",{children:[n.jsx("strong",{children:al(y)}),n.jsxs("span",{children:[T.length," 个模型"]})]})]}),n.jsx("div",{className:"model-compact-grid",children:T.map(k=>n.jsx(gp,{model:k,onCopy:m,onUpdate:r,onDelete:O},k.id))})]},y))}),me>1&&n.jsxs("div",{className:"pager",children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>te(y=>Math.max(1,y-1)),disabled:Z<=1,children:"上一页"}),n.jsxs("span",{children:[Z," / ",me]}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>te(y=>Math.min(me,y+1)),disabled:Z>=me,children:"下一页"})]})]}):n.jsx(qt,{text:c.length?"没有匹配的模型":"暂无模型,请先添加你要开放给用户调用的模型 ID"})]})]})}function gp({model:c,onCopy:m,onUpdate:p,onDelete:r}){const O=be(c.aliases).slice(0,3),R=c.status==="disabled";return n.jsxs("article",{className:"model-compact-row",children:[n.jsxs("div",{className:"model-compact-main",children:[n.jsx("strong",{children:c.name}),n.jsx("small",{children:c.id}),O.length>0&&n.jsx("span",{children:O.map(L=>n.jsx("em",{children:L},L))})]}),n.jsxs("div",{className:"model-row-actions",children:[n.jsx(zt,{tone:c.status,children:Mt(c.status)}),c.recommended&&n.jsx("span",{className:"model-recommended-mark",children:"推荐"}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>m(c.id,"模型 ID 已复制"),children:n.jsx(Et,{name:"copy"})}),n.jsxs("details",{className:"model-row-menu",children:[n.jsx("summary",{"aria-label":"模型操作",children:"•••"}),n.jsxs("div",{children:[n.jsx("button",{type:"button",onClick:()=>p(c.id,{recommended:!c.recommended}),children:c.recommended?"取消推荐":"设为推荐"}),n.jsx("button",{type:"button",onClick:()=>p(c.id,{status:R?"available":"disabled"}),children:R?"启用模型":"停用模型"}),n.jsx("button",{className:"is-danger",type:"button",onClick:()=>r(c.id),children:"删除模型"})]})]})]})]})}function xp({model:c,featured:m=!1,onCopy:p,onUpdate:r}){return n.jsxs("article",{className:m?"model-card featured":"model-card",children:[n.jsxs("div",{className:"model-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:c.name}),n.jsxs("span",{children:[c.vendor," · ",c.category]})]}),n.jsx(zt,{tone:c.status,children:Mt(c.status)})]}),n.jsx("p",{children:c.description}),n.jsx("div",{className:"alias-row",children:be(c.aliases).map(O=>n.jsx("span",{children:O},O))}),n.jsxs("div",{className:"model-meta",children:[n.jsxs("span",{children:["价格:",c.price]}),n.jsx("span",{children:c.context})]}),n.jsxs("div",{className:"model-id",children:[n.jsx("code",{children:c.id}),n.jsx("button",{className:"icon-button",title:"复制模型 ID",onClick:()=>p(c.id,"模型 ID 已复制"),children:n.jsx(Et,{name:"copy"})})]}),r&&n.jsxs("div",{className:"model-card-actions",children:[n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(c.id,{recommended:!1}),children:"取消推荐"}),n.jsx("button",{className:"secondary-button compact-button",type:"button",onClick:()=>r(c.id,{status:c.status==="disabled"?"available":"disabled"}),children:c.status==="disabled"?"启用":"停用"})]})]})}function jp({channels:c,onCreate:m,onImport:p,onCheckAccounts:r,onDeduplicateAccounts:O,onDeleteAccount:R,onUpdate:L,onStartOAuth:P,onCompleteOAuth:z}){const g=c.filter(y=>y.provider==="codex"||y.provider==="openai"||be(y.models).some(T=>T.includes("image"))),[q,_]=x.useState(""),[ee,te]=x.useState({}),[fe,le]=x.useState({}),[se,ie]=x.useState({}),[ge,re]=x.useState({}),[Ne,$]=x.useState(""),[ve,U]=x.useState(""),[F,ce]=x.useState(""),xe=24,Te=48;async function ae(y,T){_(`import:${y}`);try{await p(y,T)}finally{_("")}}async function Q(y,T=!1,k=""){_(k?`check-account:${k}`:`${T?"retry":"check"}:${y}`);try{await r(y,T,k)}finally{_("")}}async function me(y){_(`dedupe:${y}`);try{await O(y)}finally{_("")}}function Z(y){const T=be(y.openaiAccounts).map(A=>[A.email||A.name||A.accountId||A.id,A.accountId||"",A.status||"unchecked",A.credentialMode||"access-token",A.planType||"",A.expiresAt||"",A.lastCheckedAt||"",A.lastUsedAt||"",String(A.requestCount||0),A.lastErrorCode||"",A.lastError||""]),k=A=>`"${A.replace(/"/g,'""')}"`,d=[["账号","Account ID","状态","凭据方式","套餐","到期时间","最近检测","最近调用","调用次数","错误码","最后错误"],...T].map(A=>A.map(k).join(",")).join(`\r -`),M=new Blob(["\uFEFF"+d],{type:"text/csv;charset=utf-8"}),G=URL.createObjectURL(M),X=document.createElement("a");X.href=G,X.download=`${y.name||"account-pool"}-health-report.csv`,X.click(),URL.revokeObjectURL(G)}async function C(y){_(`status:${y.id}`);try{await L(y.id,{status:y.status==="disabled"?"healthy":"disabled",baseUrl:y.baseUrl||Cs(y.provider)||As,provider:y.provider||"codex",models:be(y.models).length?y.models:bm.split(",").map(T=>T.trim())})}finally{_("")}}async function Y(y,T){const k=T.email||T.name||T.accountId||T.id;if(window.confirm(`删除账号「${k}」?`)){_(`delete-account:${T.id}`);try{await R(y.id,T.id)}finally{_("")}}}return n.jsxs(lt,{title:"账号池",children:[n.jsxs("div",{className:"panel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"账号有两种来源,任选其一即可。"}),n.jsx("button",{className:"primary-button",onClick:()=>m(gm("codex")),children:"新增账号池渠道"})]}),n.jsxs("div",{className:"source-guide",children:[n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"网页会话(推荐)"}),n.jsx("span",{children:"支持完整 auth/session JSON 或浏览器 Session Cookie,并在调用前重新获取 accessToken。"})]}),n.jsxs("div",{className:"source-guide-item",children:[n.jsx("strong",{children:"批量导入"}),n.jsx("span",{children:"支持 JSON、ZIP、TXT;TXT 可使用 JSONL 或每行一个 access token。"})]})]}),n.jsxs("div",{className:"channels-stack",children:[g.map(y=>{const T=be(y.openaiAccounts),k=T.filter(v=>v.status==="healthy").length,d=T.filter(v=>v.status==="invalid").length,M=T.filter(v=>!!v.lastErrorCode).length,G=Math.max(0,T.length-k-d),X=T.filter(v=>v.credentialMode==="refreshable").length,A=T.filter(v=>v.credentialMode==="browser-session").length,I=Math.max(0,T.length-X-A),oe=fe[y.id]||"all",Qe=(se[y.id]||"").trim().toLowerCase(),He=T.filter(v=>{const je=oe==="all"||oe==="attention"&&Op(v)||oe==="invalid"&&v.status==="invalid"||oe==="error"&&!!v.lastErrorCode||oe==="refreshable"&&v.credentialMode==="refreshable",$e=`${v.email||""} ${v.name||""} ${v.accountId||""} ${v.userId||""} ${v.lastError||""}`.toLowerCase();return je&&(!Qe||$e.includes(Qe))}),dt=ge[y.id]||"pool",V=[...He].sort((v,je)=>{if(dt==="pool")return 0;const $e=dt==="expiry"?v.expiresAt||"9999-12-31":v.lastUsedAt||"",Ke=dt==="expiry"?je.expiresAt||"9999-12-31":je.lastUsedAt||"";return dt==="recent"?Ke.localeCompare($e):$e.localeCompare(Ke)}),Je=Math.min(V.length,ee[y.id]||xe),ut=V.slice(0,Je),Pe=Math.max(0,V.length-ut.length),Ft=Pe===0;return n.jsxs("div",{className:"channel-card",children:[n.jsxs("div",{className:"channel-card-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:y.name}),n.jsx("span",{children:y.baseUrl||Cs(y.provider)||As}),n.jsxs("small",{children:["账号 ",T.length," 个,可用 ",k,",无效 ",d,",未验证 ",G]}),n.jsxs("small",{children:["可续期 ",X," · 网页会话 ",A," · 仅 Token ",I]}),n.jsxs("small",{children:["自动检测 ",y.lastCheckedAt?Wt(y.lastCheckedAt):"等待首次检测"]})]}),n.jsxs("div",{className:"channel-card-head-actions",children:[n.jsx(zt,{tone:y.status,children:Mt(y.status)}),n.jsx("button",{className:"primary-button compact-button",onClick:()=>ce(y.id),disabled:q!=="",children:"添加账号"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>Q(y.id),disabled:q!==""||T.length===0,children:q===`check:${y.id}`?"检测中":"批量检测"}),d>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>Q(y.id,!0),disabled:q!=="",children:q===`retry:${y.id}`?"复检中":`复检无效 ${d}`}),T.length>1&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>me(y.id),disabled:q!=="",children:q===`dedupe:${y.id}`?"去重中":"账号去重"}),T.length>0&&n.jsx("button",{className:"secondary-button compact-button",onClick:()=>Z(y),disabled:q!=="",children:"导出报告"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>C(y),disabled:q!=="",children:y.status==="disabled"?"启用渠道":"停用渠道"})]})]}),n.jsxs("div",{className:"account-filter-bar",role:"group","aria-label":"账号筛选",children:[n.jsx("input",{value:se[y.id]||"",onChange:v=>ie(je=>({...je,[y.id]:v.target.value})),placeholder:"搜索账号或错误","aria-label":"搜索账号"}),n.jsxs("select",{value:dt,onChange:v=>re(je=>({...je,[y.id]:v.target.value})),"aria-label":"账号排序",children:[n.jsx("option",{value:"pool",children:"账号池顺序"}),n.jsx("option",{value:"oldest",children:"最久未用优先"}),n.jsx("option",{value:"recent",children:"最近使用优先"}),n.jsx("option",{value:"expiry",children:"最早到期优先"})]}),[["all",`全部 ${T.length}`],["attention","需关注"],["invalid",`无效 ${d}`],["error",`有错误 ${M}`],["refreshable",`可续期 ${X}`]].map(([v,je])=>n.jsx("button",{type:"button",className:oe===v?"selected":"",onClick:()=>le($e=>({...$e,[y.id]:v})),children:je},v))]}),n.jsxs("div",{className:"metrics-grid",children:[n.jsx(nl,{label:"账号总数",value:T.length}),n.jsx(nl,{label:"可用账号",value:k}),n.jsx(nl,{label:"无效账号",value:d}),n.jsx(nl,{label:"未验证账号",value:G})]}),n.jsx("div",{className:"drawing-channel-models",children:be(y.models).length?be(y.models).map(v=>n.jsx("span",{children:v},v)):n.jsx("span",{children:"未绑定绘图模型"})}),T.length>0&&n.jsxs("div",{className:"account-pool-list",children:[ut.map(v=>n.jsxs("div",{className:"account-pool-row",children:[n.jsxs("div",{className:"account-pool-main",children:[n.jsxs("div",{children:[n.jsxs("div",{className:"account-pool-title",children:[n.jsx("strong",{title:v.email||v.name||v.accountId||v.id,children:v.email||v.name||v.accountId||v.id}),n.jsx("span",{className:`source-tag source-tag-${v.source==="web-login"?"web":"manual"}`,children:v.source==="web-login"?"网页登录":v.source==="web-oauth"?"网页 OAuth":v.source==="oauth"?"Codex OAuth":"导入"})]}),n.jsx("span",{children:v.lastError?`${dm(v.lastErrorCode)}${dm(v.lastErrorCode)?" · ":""}${v.lastError}`:v.lastCheckedAt?`上次检测 ${Wt(v.lastCheckedAt)}`:"未检测"}),n.jsxs("span",{children:[v.credentialMode==="refreshable"?"可自动续期":v.credentialMode==="browser-session"?"依赖网页会话":"仅 access token",v.expiresAt?` · 到期 ${Wt(v.expiresAt)}`:""]}),n.jsxs("span",{children:["套餐 ",P0(v.planType)]}),v.lastUsedAt&&n.jsxs("span",{children:["最近调用 ",Wt(v.lastUsedAt)," · ",v.requestCount||0," 次"]})]}),n.jsx(Tp,{limits:v.quotaLimits})]}),n.jsxs("div",{className:"account-pool-meta",children:[n.jsx(zt,{tone:v.status==="healthy"?"healthy":v.status==="invalid"?"disabled":"standby",children:v.status==="healthy"?"可用":v.status==="invalid"?"无效":"未验证"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",disabled:q!=="",onClick:()=>Q(y.id,!1,v.id),children:q===`check-account:${v.id}`?"检测中":"检测"}),n.jsx("button",{type:"button",className:"danger-button compact-button",disabled:q!=="",onClick:()=>Y(y,v),children:q===`delete-account:${v.id}`?"删除中":"删除"})]})]},v.id)),He.length===0&&n.jsx(qt,{text:"没有匹配的账号"}),V.length>xe&&n.jsxs("div",{className:"account-pool-more",children:[n.jsx("span",{className:"muted-inline",children:Ft?`已显示全部 ${V.length} 个账号`:`已显示 ${ut.length} 个,还有 ${Pe} 个`}),n.jsxs("div",{className:"account-pool-more-actions",children:[!Ft&&n.jsxs("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(v=>({...v,[y.id]:Math.min(V.length,Je+Te)})),children:["再显示 ",Math.min(Te,Pe)," 个"]}),!Ft&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(v=>({...v,[y.id]:V.length})),children:"全部显示"}),Je>xe&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>te(v=>({...v,[y.id]:xe})),children:"收起"})]})]})]})]},y.id)}),g.length===0&&n.jsx(qt,{text:"暂无绘图渠道,先新增一个 OpenAI 账号池渠道"})]}),Ne&&n.jsx(Cp,{channelId:Ne,onStart:P,onComplete:z,onClose:()=>$("")}),F&&n.jsx(Sp,{busy:q!=="",onAuthSession:()=>{U(F),ce("")},onImport:async y=>{await ae(F,y),ce("")},onClose:()=>ce("")}),ve&&n.jsx(Ap,{onImport:async y=>{await ae(ve,new File([JSON.stringify(Np(y))],"authsession.json",{type:"application/json"}))},onClose:()=>U("")})]})}function Sp({busy:c,onAuthSession:m,onImport:p,onClose:r}){return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card account-add-modal",onClick:O=>O.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"添加账号"}),n.jsx("span",{children:"选择一种账号接入方式"})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsxs("div",{className:"account-add-options",children:[n.jsxs("button",{type:"button",className:"account-add-option recommended",onClick:m,disabled:c,children:[n.jsx("span",{className:"account-add-icon",children:"A"}),n.jsx("strong",{children:"导入网页会话"}),n.jsx("small",{children:"粘贴完整 authsession JSON,保留 sessionToken"})]}),n.jsxs("label",{className:`account-add-option${c?" disabled":""}`,children:[n.jsx("span",{className:"account-add-icon",children:"J"}),n.jsx("strong",{children:c?"导入中":"导入 JSON / ZIP / TXT"}),n.jsx("small",{children:"批量导入已有账号文件"}),n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:c,onChange:O=>{const R=O.target.files?.[0];R&&p(R),O.target.value=""}})]})]}),n.jsx("div",{className:"modal-actions",children:n.jsx("button",{type:"button",className:"secondary-button",onClick:r,children:"取消"})})]})})}function Np(c){const m=c.trim(),p=m.match(/(?:^|[;\s])(__Secure-(?:next-auth|authjs)\.session-token)=([^;\s]+)/);if(p)return{sessionToken:p[2],source:"web-login"};try{const r=JSON.parse(m),O=r.tokens&&typeof r.tokens=="object"?r.tokens:{},R=q=>typeof r[q]=="string"?r[q]:typeof O[q]=="string"?O[q]:"",L=R("accessToken")||R("access_token"),P=R("refreshToken")||R("refresh_token"),z=R("sessionToken")||R("session_token"),g=r.user&&typeof r.user=="object"?r.user:{};if(L||P||z)return{accessToken:L||void 0,refreshToken:P||void 0,sessionToken:z||void 0,email:typeof g.email=="string"?g.email:void 0,name:typeof g.name=="string"?g.name:void 0,source:"web-login"}}catch{}return{sessionToken:m,source:"web-login"}}function Ap({onImport:c,onClose:m}){const[p,r]=x.useState(""),[O,R]=x.useState(!1),[L,P]=x.useState(""),[z,g]=x.useState("");async function q(){if(!p.trim()){P("请粘贴 authsession");return}R(!0),P(""),g("");try{await c(p.trim()),r(""),g("已导入,继续粘贴下一条即可")}catch(_){P(_ instanceof Error?_.message:"导入失败")}finally{R(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:m,children:n.jsxs("div",{className:"modal-card",onClick:_=>_.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"添加网页会话"}),n.jsx("button",{type:"button",className:"icon-button",onClick:m,children:"×"})]}),n.jsxs("p",{className:"muted-inline",children:["可直接粘贴 chatgpt.com/api/auth/session 的完整 JSON;也支持浏览器 ",n.jsx("code",{children:"__Secure-next-auth.session-token"})," 的值或完整 Cookie 字符串。"]}),n.jsxs("label",{className:"authsession-field",children:[n.jsx("span",{children:"authsession"}),n.jsx("textarea",{autoFocus:!0,value:p,onChange:_=>r(_.target.value),placeholder:"eyJhbGci..."})]}),L&&n.jsx("div",{className:"form-error",children:L}),z&&n.jsx("div",{className:"form-success",children:z}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:m,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:O,onClick:q,children:O?"导入中":"导入账号"})]})]})})}function Cp({channelId:c,onStart:m,onComplete:p,onClose:r}){const[O,R]=x.useState(""),[L,P]=x.useState(""),[z,g]=x.useState(""),[q,_]=x.useState(!1),[ee,te]=x.useState("");async function fe(){_(!0),te("");try{const se=await m(c);R(se.authorizeUrl),P(se.state),window.open(se.authorizeUrl,"_blank","noopener")}catch(se){te(se instanceof Error?se.message:"发起授权失败")}finally{_(!1)}}async function le(){if(!z.trim()){te("请粘贴授权完成后浏览器跳转的回调地址");return}_(!0),te("");try{await p(c,{callbackUrl:z.trim(),state:L}),r()}catch(se){te(se instanceof Error?se.message:"完成授权失败")}finally{_(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:r,children:n.jsxs("div",{className:"modal-card",onClick:se=>se.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsx("strong",{children:"OAuth 授权添加网页账号"}),n.jsx("button",{type:"button",className:"icon-button",onClick:r,children:"×"})]}),n.jsx("p",{className:"muted-inline",children:"使用 ChatGPT 网页兼容的 OAuth 客户端获取 refresh_token,只调用网页 backend-api,不会走 Codex 接口。"}),n.jsxs("ol",{className:"oauth-steps",children:[n.jsxs("li",{children:[n.jsx("button",{type:"button",className:"primary-button",onClick:fe,disabled:q,children:O?"重新生成授权链接":"① 生成授权链接并打开"}),O&&n.jsxs("div",{className:"oauth-link",children:[n.jsx("input",{readOnly:!0,value:O,onFocus:se=>se.target.select()}),n.jsx("span",{className:"muted-inline",children:"若未自动打开,复制到浏览器手动访问,用要添加的 ChatGPT 账号登录授权。"})]})]}),n.jsxs("li",{children:[n.jsx("label",{children:"② 粘贴授权后浏览器跳转的完整回调地址"}),n.jsx("input",{value:z,placeholder:"https://platform.openai.com/auth/callback?code=...&state=...",onChange:se=>g(se.target.value),disabled:!O||q})]})]}),ee&&n.jsx("p",{className:"form-error",children:ee}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:r,disabled:q,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",onClick:le,disabled:!O||q,children:q?"处理中":"完成授权"})]})]})})}function Tp({limits:c}){const m=be(c).filter(p=>p.label||p.name).slice(0,3);return m.length?n.jsx("div",{className:"quota-bars",children:m.map(p=>{const r=Ep(p);return n.jsxs("div",{className:"quota-bar",children:[n.jsxs("div",{className:"quota-bar-label",children:[n.jsx("strong",{children:p.label||p.name}),n.jsx("span",{children:Mp(p,r)})]}),n.jsx("div",{className:"quota-bar-track",children:n.jsx("span",{style:{width:`${r}%`}})})]},`${p.label||p.name}-${p.resetAt||""}`)})}):null}function Ep(c){return typeof c.percentRemaining=="number"&&Number.isFinite(c.percentRemaining)?Math.max(0,Math.min(100,c.percentRemaining)):typeof c.remaining=="number"&&typeof c.limit=="number"&&c.limit>0?Math.max(0,Math.min(100,c.remaining/c.limit*100)):typeof c.used=="number"&&typeof c.limit=="number"&&c.limit>0?Math.max(0,Math.min(100,(c.limit-c.used)/c.limit*100)):0}function Mp(c,m){const p=c.resetAt?` · ${Wt(c.resetAt)}`:"";return typeof c.remaining=="number"?`${Math.round(m)}% 剩余${p}`:`${Math.round(m)}%${p}`}function zp(c){const m=be(c.models).join(" ").toLowerCase(),p=["对话"];c.streamMode!=="disabled"&&p.push("流式"),/(image|dall-e|gpt-image)/.test(m)&&p.push("图片"),(c.openaiAccountCount??c.openaiAccounts?.length??0)>0&&p.push("账号池");const r=c.upstreamKeyCount??0;return r>1&&p.push(`${r} Key 轮询`),p}function Op(c){if(c.status==="invalid"||c.credentialMode==="browser-session")return!0;if(!c.expiresAt)return!1;const m=new Date(c.expiresAt).getTime();return Number.isFinite(m)&&m-Date.now()<=1440*60*1e3}function _p({channels:c,groups:m,onUpdate:p,onCreate:r,onImport:O,onDelete:R,onSyncModels:L,onCheck:P}){const z=Sa("openai"),[g,q]=x.useState(!1),[_,ee]=x.useState(z.provider),[te,fe]=x.useState(z.name),[le,se]=x.useState(z.baseUrl),[ie,ge]=x.useState(z.models.join(", ")),[re,Ne]=x.useState(""),[$,ve]=x.useState(""),[U,F]=x.useState(!1),[ce,xe]=x.useState(!1);function Te(Q){const me=Sa(Q);ee(me.provider),fe(me.name),se(me.baseUrl),ge(me.models.join(", ")),ve("")}async function ae(Q){Q.preventDefault(),F(!0),ve("");try{await r({name:te.trim()||Sa(_).name,provider:_,baseUrl:le.trim(),...xm(re),models:Ic(ie),streamMode:"auto"}),q(!1),Ne(""),Te(_)}catch(me){ve(me instanceof Error?me.message:"渠道创建失败")}finally{F(!1)}}return n.jsxs(lt,{title:"渠道",children:[n.jsxs("div",{className:"channel-page-intro",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"管理上游服务"}),n.jsx("span",{children:"每个渠道对应一个 API 上游。先添加渠道,再检测连通性并同步可用模型。"})]}),n.jsxs("div",{className:"channel-page-summary",children:[n.jsxs("span",{children:[n.jsx("b",{children:c.length})," 个渠道"]}),n.jsxs("span",{children:[n.jsx("b",{children:c.filter(Q=>Q.status!=="disabled").length})," 个已启用"]})]})]}),n.jsxs("div",{className:"panel-toolbar channel-toolbar",children:[n.jsx("span",{className:"muted-inline",children:"列表显示当前状态;点击任一渠道可修改连接、模型和计费设置。"}),n.jsx("button",{className:"primary-button",onClick:()=>q(Q=>!Q),children:g?"取消新增":"+ 新增渠道"})]}),g&&n.jsxs("form",{className:"channel-card channel-create-form",onSubmit:ae,children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"选择渠道类型"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:Sa(_).label}),n.jsx("small",{children:"选择后自动填入建议配置"})]}),n.jsx("div",{role:"listbox","aria-label":"选择渠道类型",children:Fc.map(Q=>n.jsxs("button",{type:"button",className:_===Q.provider?"selected":"",onClick:me=>{Te(Q.provider),me.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:Q.label}),n.jsx("span",{children:"使用推荐的名称和地址"})]},Q.provider))})]})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:te,onChange:Q=>fe(Q.target.value),placeholder:"例如 OpenAI 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:al(_),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:le,onChange:Q=>se(Q.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"上游 Key"}),n.jsx("textarea",{className:"channel-key-input",value:re,onChange:Q=>Ne(Q.target.value),placeholder:_==="codex"?"账号池导入后使用":_==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发",autoComplete:"off",rows:3})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsx("button",{type:"button",className:"model-pull-button",onClick:()=>{if(_!=="codex"&&!le.trim()){ve("请先填写 Base URL 再获取模型");return}ve(""),xe(!0)},children:"从上游获取模型"})]}),n.jsx("textarea",{value:ie,onChange:Q=>ge(Q.target.value),placeholder:"多个模型用逗号分隔,或点上方『从上游获取模型』拉取后多选"})]})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("span",{className:"model-create-message",role:"status",children:$}),n.jsx("button",{className:"secondary-button",type:"button",onClick:()=>Te(_),disabled:U,children:"填入模板"}),n.jsx("button",{className:"primary-button",type:"submit",disabled:U,children:U?"创建中":"创建渠道"})]})]}),g&&ce&&n.jsx(jm,{subtitle:`${te.trim()||Sa(_).name} · 勾选需要接入的模型`,current:Ic(ie),loadModels:async()=>{const Q=await pe("/api/channel-model-preview",{method:"POST",body:JSON.stringify({provider:_,baseUrl:le.trim(),upstreamApiKey:re})});return be(Q.models)},onConfirm:async Q=>{ge(Q.join(", "))},onClose:()=>xe(!1)}),n.jsxs("div",{className:"channels-stack",children:[c.map(Q=>n.jsx(Dp,{channel:Q,groups:m,onUpdate:p,onImport:O,onDelete:R,onSyncModels:L,onCheck:P},Q.id)),c.length===0&&n.jsx(qt,{text:"暂无渠道,先在后端添加渠道接口或导入配置"})]})]})}function Dp({channel:c,groups:m,onUpdate:p,onImport:r,onDelete:O,onSyncModels:R,onCheck:L}){const[P,z]=x.useState(c.name),[g,q]=x.useState(c.provider),[_,ee]=x.useState(c.streamMode||"auto"),[te,fe]=x.useState(c.baseUrl),[le,se]=x.useState(be(c.allowedGroupIds)),[ie,ge]=x.useState(be(c.models).join(", ")),[re,Ne]=x.useState("saved"),[$,ve]=x.useState(String(c.inputPricePer1K||0)),[U,F]=x.useState(String(c.outputPricePer1K||0)),[ce,xe]=x.useState(!!c.webEndpoint),[Te,ae]=x.useState(""),[Q,me]=x.useState(""),[Z,C]=x.useState(!1),Y=c.openaiAccountCount??c.openaiAccounts?.length??0,y=be(c.models).length,T=zp(c),k=c.status==="disabled",d={saved:"已保存",template:"模板",manual:"手动",synced:"上游同步"}[re],M=js.find(V=>V.value===_)||js[0],G={auto:"自动处理(推荐)",real:"强制流式",fake:"兼容流式",disabled:"关闭流式"};x.useEffect(()=>{z(c.name),q(c.provider),ee(c.streamMode||"auto"),fe(c.baseUrl),se(be(c.allowedGroupIds)),ge(be(c.models).join(", ")),Ne("saved"),ve(String(c.inputPricePer1K||0)),F(String(c.outputPricePer1K||0)),xe(!!c.webEndpoint),ae("")},[c.id,c.name,c.provider,c.streamMode,c.baseUrl,c.models,c.inputPricePer1K,c.outputPricePer1K,c.webEndpoint]);async function X(){const V=A();me("save");try{await p(c.id,V),ae("")}finally{me("")}}function A(){const V=Cs(g),Je=!/^https?:\/\//i.test(te.trim())&&V?V:te,ut={name:P.trim()||c.name,provider:g,streamMode:_,baseUrl:Je,inputPricePer1K:Number($)||0,outputPricePer1K:Number(U)||0,webEndpoint:ce,models:ie.split(",").map(Pe=>Pe.trim()).filter(Boolean),allowedGroupIds:le};return Object.assign(ut,xm(Te)),ut}async function I(){const V=c.status==="disabled"?"healthy":"disabled";me("status");try{await p(c.id,{...A(),status:V}),ae("")}finally{me("")}}async function oe(){me("sync");try{await p(c.id,A()),ae(""),C(!0)}finally{me("")}}function Qe(){const V=Sa(g);ge(V.models.join(", ")),Ne("template"),V.baseUrl&&!/^https?:\/\//i.test(te.trim())&&fe(V.baseUrl)}async function He(){me("check");try{await X(),await L(c.id)}finally{me("")}}async function dt(V){me("import");try{await r(c.id,V)}finally{me("")}}return n.jsxs(n.Fragment,{children:[n.jsxs("details",{className:"channel-card channel-card-collapsible",children:[n.jsxs("summary",{className:"channel-card-head channel-list-row",children:[n.jsxs("div",{className:"channel-identity",children:[n.jsx("strong",{children:c.name}),n.jsx("span",{children:al(g)}),n.jsx("small",{children:c.baseUrl||"尚未配置上游地址"}),n.jsx("div",{className:"channel-capability-tags",children:T.map(V=>n.jsx("span",{children:V},V))})]}),n.jsxs("div",{className:"channel-list-meta",children:[n.jsxs("span",{children:[n.jsx("b",{children:y})," 个模型"]}),Y>0&&n.jsxs("span",{children:[n.jsx("b",{children:Y})," 个账号"]})]}),n.jsxs("div",{className:"channel-check-result",children:[n.jsx("span",{children:"连通性"}),n.jsx("b",{className:c.lastError?"is-error":c.lastCheckedAt?"is-ok":"",children:c.lastError?"检测失败":c.lastCheckedAt?`已检测 ${Wt(c.lastCheckedAt)}`:"尚未检测"})]}),n.jsxs("div",{className:"channel-list-status",children:[n.jsx(zt,{tone:c.status,children:k?"已停用":Mt(c.status)}),n.jsx("span",{className:"channel-expand-hint",children:"配置"})]})]}),n.jsxs("div",{className:"channel-editor-controls",children:[n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"供应商"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:al(g)}),n.jsx("small",{children:"修改上游协议类型"})]}),n.jsx("div",{role:"listbox","aria-label":"供应商",children:eo.map(V=>n.jsxs("button",{type:"button",className:g===V.value?"selected":"",onClick:Je=>{q(V.value);const ut=Cs(V.value);ut&&!/^https?:\/\//i.test(te.trim())&&fe(ut),Je.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:V.label}),n.jsx("span",{children:V.value==="compatible"?"适用于兼容 OpenAI 格式的服务":"选择对应的上游协议"})]},V.value))})]})]}),n.jsxs("label",{className:"channel-select-field",children:[n.jsx("span",{children:"响应方式"}),n.jsxs("details",{className:"channel-choice-menu",children:[n.jsxs("summary",{children:[n.jsx("span",{children:G[M.value]}),n.jsx("small",{children:M.description})]}),n.jsx("div",{role:"listbox","aria-label":"响应方式",children:js.map(V=>n.jsxs("button",{type:"button",className:_===V.value?"selected":"",onClick:Je=>{ee(V.value),Je.currentTarget.closest("details")?.removeAttribute("open")},children:[n.jsx("strong",{children:G[V.value]}),n.jsx("span",{children:V.description})]},V.value))})]})]})]}),(g==="codex"||Y>0)&&n.jsxs("div",{className:"setting",children:[n.jsxs("div",{children:[n.jsx("span",{children:"网页对话接口"}),n.jsx("small",{children:"开启后走 ChatGPT 网页对话接口,把 Plus 订阅账号包装成 API"})]}),n.jsx("div",{className:"setting-value",children:n.jsx("button",{type:"button",className:ce?"ios-switch is-on":"ios-switch","aria-label":ce?"关闭网页对话接口":"开启网页对话接口","aria-pressed":ce,onClick:()=>xe(V=>!V),children:n.jsx("span",{})})})]}),n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"渠道名称"}),n.jsx("input",{value:P,onChange:V=>z(V.target.value),placeholder:"例如 Gemini 主线路"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"供应商"}),n.jsx("input",{value:al(g),readOnly:!0})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsx("span",{children:"Base URL"}),n.jsx("input",{value:te,onChange:V=>fe(V.target.value),placeholder:"https://provider.example/v1"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"优先级"}),n.jsx("input",{value:c.priority,readOnly:!0})]}),n.jsxs("div",{className:"channel-form-wide channel-model-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"模型"}),n.jsxs("small",{children:["来源:",d]})]}),n.jsx("textarea",{value:ie,onChange:V=>{ge(V.target.value),Ne("manual")},placeholder:"优先拉取上游模型,也可以手动补充,多个用逗号分隔"}),n.jsxs("div",{className:"channel-model-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:Qe,disabled:Q!=="",children:"填入模板"}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:oe,disabled:Q!=="",children:Q==="sync"?"拉取中":"获取上游模型"})]})]}),n.jsxs("label",{className:"channel-form-wide",children:[n.jsxs("span",{children:["上游 Key",(c.upstreamKeyCount??0)>0?` (已配置 ${c.upstreamKeyCount} 个)`:c.upstreamKeySet?" (已配置)":""]}),n.jsx("textarea",{className:"channel-key-input",value:Te,onChange:V=>ae(V.target.value),placeholder:g==="codex"?"Codex 账号池不需要上游 Key":g==="cpa"?"填写 CPA 的 API key,多个每行一个":"每行一个 Key;填多个会自动轮询分发;留空不修改",autoComplete:"off",rows:3})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输入单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:$,onChange:V=>ve(V.target.value)})]}),n.jsxs("label",{children:[n.jsx("span",{children:"输出单价 / 1K Token"}),n.jsx("input",{type:"number",min:"0",step:"0.0001",value:U,onChange:V=>F(V.target.value)})]}),n.jsx("span",{className:"channel-billing-note",children:"定价可先留空;接入是否可用优先看渠道检测和模型同步结果。"})]}),n.jsxs("div",{className:"channel-group-field",children:[n.jsxs("div",{className:"field-label-row",children:[n.jsx("span",{children:"可见分组"}),n.jsx("small",{children:le.length?`已选择 ${le.length} 个分组`:"全部用户可用"})]}),m.length===0?n.jsx("p",{className:"channel-group-empty",children:"还没有用户分组。去「分组」页创建后,可在这里把渠道限制为只对特定分组开放。"}):n.jsx("div",{className:"channel-group-options",children:m.map(V=>{const Je=le.includes(V.id);return n.jsxs("button",{type:"button",className:Je?"selected":"","aria-pressed":Je,onClick:()=>se(ut=>Je?ut.filter(Pe=>Pe!==V.id):[...ut,V.id]),children:[n.jsx("span",{children:V.name}),V.description&&n.jsx("small",{children:V.description})]},V.id)})})]}),n.jsxs("div",{className:"channel-card-actions",children:[n.jsx("button",{className:"secondary-button",onClick:He,disabled:Q!=="",children:Q==="check"?"检测中":"检测渠道"}),n.jsx("button",{className:"primary-button",onClick:X,disabled:Q!=="",children:Q==="save"?"保存中":"保存"}),n.jsxs("details",{className:"channel-more-actions",children:[n.jsx("summary",{children:"更多操作"}),n.jsxs("div",{children:[n.jsxs("label",{className:"secondary-button",children:[Q==="import"?"导入中":"导入账号 JSON",n.jsx("input",{type:"file",accept:"application/json,application/zip,text/plain,.json,.zip,.txt",disabled:Q!=="",onChange:V=>{const Je=V.target.files?.[0];Je&&dt(Je),V.target.value=""}})]}),n.jsx("button",{className:"secondary-button",onClick:I,disabled:Q!=="",children:c.status==="disabled"?"启用渠道":"停用渠道"}),n.jsx("button",{className:"danger-button",onClick:()=>O(c.id),disabled:Q!=="",children:"删除渠道"})]})]})]})]}),Z&&n.jsx(jm,{subtitle:`${c.name} · 勾选需要接入的模型`,current:ie.split(",").map(V=>V.trim()).filter(Boolean),loadModels:async()=>{const V=await pe(`/api/channels/${c.id}/upstream-models`,{method:"POST",body:JSON.stringify({})});return be(V.models)},onConfirm:async V=>{await R(c.id,V)},onClose:()=>C(!1)})]})}function jm({subtitle:c,current:m,loadModels:p,onConfirm:r,onClose:O}){const[R,L]=x.useState(!0),[P,z]=x.useState(""),[g,q]=x.useState([]),[_,ee]=x.useState(new Set),[te,fe]=x.useState(""),[le,se]=x.useState(!1);x.useEffect(()=>{let U=!1;return(async()=>{L(!0),z("");try{const F=await p();if(U)return;const ce=new Set,xe=be(F).map(ae=>ae.trim()).filter(ae=>{if(!ae)return!1;const Q=ae.toLowerCase();return ce.has(Q)?!1:(ce.add(Q),!0)}),Te=new Set(m.map(ae=>ae.toLowerCase()));q(xe),ee(new Set(xe.filter(ae=>Te.has(ae.toLowerCase()))))}catch(F){U||z(F instanceof Error?F.message:"获取上游模型失败")}finally{U||L(!1)}})(),()=>{U=!0}},[]);const ie=te.trim().toLowerCase(),ge=ie?g.filter(U=>U.toLowerCase().includes(ie)):g,re=ge.length>0&&ge.every(U=>_.has(U));function Ne(U){ee(F=>{const ce=new Set(F);return ce.has(U)?ce.delete(U):ce.add(U),ce})}function $(){ee(U=>{const F=new Set(U);return re?ge.forEach(ce=>F.delete(ce)):ge.forEach(ce=>F.add(ce)),F})}async function ve(){const U=new Set(g.map(ae=>ae.toLowerCase())),F=m.filter(ae=>!U.has(ae.toLowerCase())),ce=g.filter(ae=>_.has(ae)),xe=new Set,Te=[...F,...ce].filter(ae=>{const Q=ae.toLowerCase();return xe.has(Q)?!1:(xe.add(Q),!0)});se(!0);try{await r(Te),O()}catch{se(!1)}}return n.jsx("div",{className:"modal-backdrop",onClick:O,children:n.jsxs("div",{className:"modal-card model-picker-modal",onClick:U=>U.stopPropagation(),children:[n.jsxs("div",{className:"modal-head",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"选择上游模型"}),n.jsx("span",{children:c})]}),n.jsx("button",{type:"button",className:"icon-button",onClick:O,children:"×"})]}),R?n.jsx("div",{className:"model-picker-status",children:"正在获取上游模型…"}):P?n.jsx("div",{className:"model-picker-status model-picker-error",children:P}):n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"model-picker-toolbar",children:[n.jsx("input",{className:"model-picker-search",value:te,onChange:U=>fe(U.target.value),placeholder:"搜索模型名称",autoFocus:!0}),n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:$,disabled:ge.length===0,children:re?"取消全选":"全选"})]}),n.jsxs("div",{className:"model-picker-count",children:["共 ",g.length," 个 · 已选 ",_.size," 个",ie?` · 匹配 ${ge.length} 个`:""]}),n.jsxs("div",{className:"model-picker-list",children:[ge.map(U=>{const F=_.has(U),ce=m.some(xe=>xe.toLowerCase()===U.toLowerCase());return n.jsxs("label",{className:`model-picker-row${F?" checked":""}`,children:[n.jsx("input",{type:"checkbox",checked:F,onChange:()=>Ne(U)}),n.jsx("span",{className:"model-picker-name",children:U}),ce&&n.jsx("span",{className:"model-picker-tag",children:"已接入"})]},U)}),ge.length===0&&n.jsx("div",{className:"model-picker-status",children:"没有匹配的模型"})]})]}),n.jsxs("div",{className:"modal-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",onClick:O,children:"取消"}),n.jsx("button",{type:"button",className:"primary-button",disabled:R||!!P||le,onClick:ve,children:le?"保存中":`导入所选 (${_.size})`})]})]})})}function Up({logs:c,onCopy:m}){const[p,r]=x.useState(c),[O,R]=x.useState(c.length),[L,P]=x.useState(1),[z,g]=x.useState(""),[q,_]=x.useState("all"),[ee,te]=x.useState(null),[fe,le]=x.useState(!1),[se,ie]=x.useState(!1),ge=25,re=Math.max(1,Math.ceil(O/ge));x.useEffect(()=>{P(1)},[z,q]),x.useEffect(()=>{L>re&&P(re)},[L,re]),x.useEffect(()=>{const $=new AbortController,ve=window.setTimeout(async()=>{le(!0);try{const U=new URLSearchParams({page:String(L),pageSize:String(ge),status:q,q:z.trim()}),F=await pe(`/api/logs?${U}`,{signal:$.signal}),ce=be(F.logs);r(ce),R(F.total||0),te(xe=>xe&&ce.some(Te=>Te.id===xe.id)?xe:null)}catch(U){U instanceof DOMException&&U.name==="AbortError"||(r([]),R(0))}finally{$.signal.aborted||le(!1)}},z?250:0);return()=>{window.clearTimeout(ve),$.abort()}},[L,z,q]);async function Ne($){if(ee?.id===$.id){te(null);return}te($),ie(!0);try{const ve=await pe(`/api/logs/${encodeURIComponent($.id)}`);te(ve.log)}catch{te($)}finally{ie(!1)}}return n.jsxs(lt,{title:"调用日志",children:[n.jsxs("div",{className:"logs-toolbar",children:[n.jsxs("div",{className:"search-box",children:[n.jsx(Et,{name:"search"}),n.jsx("input",{value:z,onChange:$=>g($.target.value),placeholder:"搜索请求 ID、用户、Key、模型、渠道或错误码"})]}),n.jsx("div",{className:"log-status-filter",role:"group","aria-label":"日志状态筛选",children:[{value:"all",label:"全部"},{value:"success",label:"成功"},{value:"failed",label:"失败"}].map($=>n.jsx("button",{type:"button",className:q===$.value?"selected":"",onClick:()=>_($.value),children:$.label},$.value))}),n.jsx("span",{className:"muted-inline",children:fe?"加载中":`共 ${O} 条`})]}),n.jsxs("div",{className:ee?"logs-layout has-detail":"logs-layout",children:[n.jsxs("div",{className:"table",children:[n.jsxs("div",{className:"table-head logs-table",children:[n.jsx("span",{children:"请求"}),n.jsx("span",{children:"模型"}),n.jsx("span",{children:"渠道"}),n.jsx("span",{children:"状态"})]}),p.map($=>n.jsx("div",{className:"log-entry",children:n.jsxs("div",{className:ee?.id===$.id?"table-row logs-table selected":"table-row logs-table",role:"button",tabIndex:0,onClick:()=>Ne($),onKeyDown:ve=>{(ve.key==="Enter"||ve.key===" ")&&Ne($)},children:[n.jsxs("span",{children:[n.jsx("strong",{children:to($)}),n.jsxs("small",{children:[$.id," · ",Wt($.createdAt)," · ",$.latencyMs,"ms"]})]}),n.jsx("span",{children:ap($)}),n.jsx("span",{children:np($)}),n.jsx(zt,{tone:$.status,children:Mt($.status)})]})},$.id)),!fe&&p.length===0&&n.jsx(qt,{text:z||q!=="all"?"没有匹配的日志":"暂无调用日志"})]}),ee&&n.jsx(Rp,{log:ee,loading:se,onCopy:m})]}),re>1&&n.jsxs("div",{className:"pagination-bar",children:[n.jsx("button",{className:"secondary-button",disabled:L<=1||fe,onClick:()=>P($=>Math.max(1,$-1)),children:"上一页"}),n.jsxs("span",{children:[L," / ",re]}),n.jsx("button",{className:"secondary-button",disabled:L>=re||fe,onClick:()=>P($=>Math.min(re,$+1)),children:"下一页"})]})]})}function Rp({log:c,loading:m,onCopy:p}){if(!c)return n.jsx("aside",{className:"log-inspector empty-inspector",children:n.jsx("span",{children:"选择一条日志查看详情"})});const r=Number(c.inputTokens||0),O=Number(c.outputTokens||0),R=typeof c.attempts=="number"?Math.max(0,c.attempts):null,L=[["请求 ID",c.id],["状态",Mt(c.status)],["时间",lp(c.createdAt)],["用户 ID",c.userId||"未识别"],["API Key",c.apiKeyPrefix?`${c.apiKeyPrefix}***`:"未识别"],["模型",c.model||"未提供"],["渠道",c.channel||"未选择"],["实际账号",c.account||"未记录"],["响应耗时",`${c.latencyMs} ms`],["尝试次数",R===null?"未记录":String(R)],["是否重试",R===null?"未记录":R>1?"是":"否"],["输入 Tokens",Na(r)],["输出 Tokens",Na(O)],["总 Tokens",Na(r+O)],["扣费",c.cost.toFixed(4)],["错误码",c.errorCode||"无"]];return n.jsxs("aside",{className:"log-inspector",children:[n.jsxs("header",{children:[n.jsxs("div",{children:[n.jsx("span",{children:m?"加载中":"日志详情"}),n.jsx("strong",{children:to(c)})]}),n.jsx(zt,{tone:c.status,children:Mt(c.status)})]}),n.jsx("div",{className:"log-detail",children:L.map(([P,z])=>n.jsxs("div",{children:[n.jsx("span",{children:P}),n.jsx("strong",{title:z,children:z})]},P))}),n.jsxs("div",{className:"log-actions",children:[n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>p(c.id,"请求 ID 已复制"),children:"复制请求 ID"}),c.errorCode&&n.jsx("button",{type:"button",className:"secondary-button compact-button",onClick:()=>p(c.errorCode||"","错误码已复制"),children:"复制错误码"})]})]})}function Hp({models:c,channels:m}){const[p,r]=x.useState(null),[O,R]=x.useState(null),[L,P]=x.useState("username"),[z,g]=x.useState("0"),[q,_]=x.useState({enabled:!0,minReward:.1,maxReward:1}),[ee,te]=x.useState({logRetentionDays:30,maxLogs:1e4,maxQuotaEntries:2e4}),[fe,le]=x.useState(null),[se,ie]=x.useState(null),[ge,re]=x.useState(""),[Ne,$]=x.useState(""),[ve,U]=x.useState(""),[F,ce]=x.useState(""),[xe,Te]=x.useState(""),[ae,Q]=x.useState(""),[me,Z]=x.useState(""),[C,Y]=x.useState(""),[y,T]=x.useState(""),[k,d]=x.useState(!1),[M,G]=x.useState("system"),X=c.find(v=>v.recommended&&v.status==="available")?.id||c.find(v=>v.status==="available")?.id||"未配置",A=m.filter(v=>v.status!=="disabled").length,I=[{value:"system",label:"系统",description:"运行概况"},{value:"cli",label:"CLI 接入",description:"一键配置"},{value:"auth",label:"注册",description:"开放方式"},{value:"check-in",label:"签到",description:"奖励范围"},{value:"admin",label:"管理员",description:"账号绑定"},{value:"discord",label:"Discord",description:"登录限制"},{value:"maintenance",label:"维护",description:"日志保留"},{value:"backup",label:"备份",description:"导出恢复"}],oe=I.find(v=>v.value===M)||I[0];x.useEffect(()=>{Promise.all([pe("/api/settings/discord"),pe("/api/settings/auth"),pe("/api/settings/check-in"),pe("/api/account/me"),pe("/api/settings/maintenance"),pe("/api/health")]).then(([v,je,$e,Ke,il,It])=>{r(Wc(v.discord)),Y(be(v.discord.blockedGuildIds).join(` -`)),R(je.auth.registrationEnabled),P(Ts(je.auth.registrationMode)),g(String(je.auth.defaultBalance||0)),_($e.checkIn),ie(Ke.account),re(Ke.account?.username||""),$(Ke.user.name||""),U(Ke.account?.email||""),ce(Ke.account?.discordUserId||""),te(il.maintenance),le(It)}).catch(()=>T("设置加载失败"))},[]);async function Qe(v=O,je=L,$e=Number(z)){if(v!==null)try{const Ke=await pe("/api/settings/auth",{method:"PATCH",body:JSON.stringify({registrationEnabled:v,registrationMode:je,defaultBalance:$e})});R(Ke.auth.registrationEnabled),P(Ts(Ke.auth.registrationMode)),g(String(Ke.auth.defaultBalance||0)),T(Ke.auth.registrationEnabled?"注册设置已保存":"已关闭用户注册")}catch(Ke){T(Ke instanceof Error?Ke.message:"注册设置保存失败")}}async function He(){O!==null&&Qe(!O,L)}async function dt(){d(!0),T("");try{const v=await pe("/api/settings/check-in",{method:"PATCH",body:JSON.stringify(q)});_(v.checkIn),T(v.checkIn.enabled?"签到奖励设置已保存":"已关闭每日签到")}catch(v){T(v instanceof Error?v.message:"签到设置保存失败")}finally{d(!1)}}async function V(){if(p){d(!0),T("");try{const v=Wc(p),je=C.split(/[\s,]+/).map(Ke=>Ke.trim()).filter(Boolean),$e=await pe("/api/settings/discord",{method:"PATCH",body:JSON.stringify({...v,blockedGuildIds:je,clientSecret:me})});r(Wc($e.discord)),Y(be($e.discord.blockedGuildIds).join(` -`)),Z(""),T("Discord 配置已保存")}catch(v){T(v instanceof Error?v.message:"保存失败,请检查填写内容")}finally{d(!1)}}}async function Je(){try{const v=await pe("/api/account/profile",{method:"PATCH",body:JSON.stringify({username:ge,displayName:Ne,email:ve,discordUserId:F,currentPassword:xe,newPassword:ae})});ie(v.account),re(v.account.username),U(v.account.email||""),ce(v.account.discordUserId||""),Te(""),Q(""),T("管理员账号已保存")}catch(v){T(v instanceof Error?v.message:"账号设置保存失败")}}async function ut(){d(!0),T("");try{const v=await pe("/api/settings/maintenance",{method:"PATCH",body:JSON.stringify(ee)});te(v.maintenance),T("维护设置已保存,历史数据已按新规则清理")}catch(v){T(v instanceof Error?v.message:"维护设置保存失败")}finally{d(!1)}}async function Pe(){d(!0),T("");try{const v=await fetch("/api/backup",{credentials:"include"});if(!v.ok)throw new Error("备份导出失败");const je=await v.blob(),Ke=(v.headers.get("Content-Disposition")||"").match(/filename="([^"]+)"/)?.[1]||"capi-backup.json",il=URL.createObjectURL(je),It=document.createElement("a");It.href=il,It.download=Ke,It.click(),URL.revokeObjectURL(il),T("备份已导出,请妥善保管")}catch(v){T(v instanceof Error?v.message:"备份导出失败")}finally{d(!1)}}async function Ft(v){if(window.confirm("恢复会覆盖当前全部数据,并退出现有登录会话。确定继续?")){d(!0),T("");try{const je=await fetch("/api/restore",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:v}),$e=await je.json().catch(()=>null);if(!je.ok)throw new Error($e?.error?.message||"备份恢复失败");T(`已恢复 ${$e.users} 个用户、${$e.channels} 条渠道和 ${$e.models} 个模型,请重新登录`)}catch(je){T(je instanceof Error?je.message:"备份恢复失败")}finally{d(!1)}}}return n.jsxs("div",{className:"settings-layout",children:[n.jsx("div",{className:"settings-tabs",children:I.map(v=>n.jsxs("button",{type:"button",className:M===v.value?"selected":"",onClick:()=>G(v.value),children:[n.jsx("strong",{children:v.label}),n.jsx("small",{children:v.description})]},v.value))}),n.jsxs("div",{className:"settings-tab-note",children:[n.jsx("strong",{children:oe.label}),n.jsx("span",{children:oe.description})]}),M==="system"&&n.jsx(lt,{title:"系统设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsx($t,{label:"接口兼容",value:"OpenAI API"}),n.jsx($t,{label:"当前默认模型",value:X}),n.jsx($t,{label:"已配置渠道",value:`${m.length} 个,${A} 个启用`}),n.jsx($t,{label:"可选供应商",value:`${eo.length} 种`}),n.jsx($t,{label:"运行版本",value:`${fe?.version||"未知"} · ${fe?.commit||"未知"}`}),n.jsx($t,{label:"构建时间",value:fe?.buildTime?Wt(fe.buildTime):"本地构建"}),n.jsx($t,{label:"账号自动检测",value:"每 15 分钟自动检测一次"})]})}),M==="cli"&&n.jsxs(lt,{title:"CLI 工具接入",children:[n.jsx("p",{className:"cli-intro",children:"CAPI 兼容 OpenAI 和 Anthropic 协议,常见 AI 命令行工具可直接接入。"}),n.jsxs("div",{className:"cli-credentials",children:[n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"Base URL"}),n.jsx("code",{children:zl()}),n.jsx("button",{type:"button",className:"copy-button","aria-label":"复制",onClick:()=>{Ss(zl()),T("已复制 Base URL")},children:n.jsx(Et,{name:"copy"})})]}),n.jsxs("div",{className:"cli-credential",children:[n.jsx("span",{children:"API Key"}),n.jsx("code",{children:"cat_你的_api_key"})]})]}),n.jsxs("div",{className:"cli-tools",children:[n.jsxs("details",{className:"cli-tool",open:!0,children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Claude Code"}),n.jsx("span",{children:"Anthropic Messages 协议"})]}),n.jsx("pre",{children:`export ANTHROPIC_BASE_URL="${zl()}" -export ANTHROPIC_AUTH_TOKEN="cat_你的_api_key" -export ANTHROPIC_MODEL="${X}" -claude`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Codex CLI"}),n.jsx("span",{children:"OpenAI Chat 协议"})]}),n.jsxs("p",{children:["编辑 ",n.jsx("code",{children:"~/.codex/config.toml"}),":"]}),n.jsx("pre",{children:`model = "${X}" -model_provider = "capi" - -[model_providers.capi] -name = "CAPI" -base_url = "${zl()}/v1" -env_key = "CAPI_KEY" -wire_api = "chat"`}),n.jsx("p",{children:"然后设置环境变量并运行:"}),n.jsx("pre",{children:`export CAPI_KEY="cat_你的_api_key" -codex`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Aider"}),n.jsx("span",{children:"OpenAI 兼容"})]}),n.jsx("pre",{children:`export OPENAI_API_BASE="${zl()}" -export OPENAI_API_KEY="cat_你的_api_key" -aider --model openai/${X}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"Cline / Roo Code / Kilo Code"}),n.jsx("span",{children:"VS Code 插件"})]}),n.jsxs("p",{children:["在插件设置中选择 ",n.jsx("strong",{children:"OpenAI Compatible"}),":"]}),n.jsx("pre",{children:`Base URL: ${zl()}/v1 -API Key: cat_你的_api_key -Model ID: ${X}`})]}),n.jsxs("details",{className:"cli-tool",children:[n.jsxs("summary",{children:[n.jsx("strong",{children:"通用 OpenAI SDK"}),n.jsx("span",{children:"Python / Node.js"})]}),n.jsx("pre",{children:`export OPENAI_BASE_URL="${zl()}" -export OPENAI_API_KEY="cat_你的_api_key"`}),n.jsx("pre",{children:`from openai import OpenAI -client = OpenAI() -response = client.chat.completions.create( - model="${X}", - messages=[{"role": "user", "content": "hello"}] -)`})]})]}),y&&n.jsx("p",{className:"cli-message",role:"status",children:y})]}),M==="maintenance"&&n.jsx(lt,{title:"维护设置",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志保留天数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"1",max:"3650",value:ee.logRetentionDays,onChange:v=>te(je=>({...je,logRetentionDays:Number(v.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"日志最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"1000000",step:"100",value:ee.maxLogs,onChange:v=>te(je=>({...je,maxLogs:Number(v.target.value)}))})})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"额度流水最大条数"}),n.jsx("div",{className:"setting-value maintenance-control",children:n.jsx("input",{type:"number",min:"100",max:"2000000",step:"100",value:ee.maxQuotaEntries,onChange:v=>te(je=>({...je,maxQuotaEntries:Number(v.target.value)}))})})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:y}),n.jsx("button",{type:"button",className:"primary-button",disabled:k,onClick:ut,children:k?"保存中":"保存维护设置"})]})]})}),M==="backup"&&n.jsx(lt,{title:"备份与恢复",children:n.jsx("div",{className:"settings-group",children:n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["备份与恢复",n.jsx("small",{children:"包含账号哈希和加密后的上游密钥,恢复时需要相同的 SECRET_KEY"})]}),n.jsxs("div",{className:"setting-value backup-actions",children:[n.jsx("button",{type:"button",className:"secondary-button",disabled:k,onClick:Pe,children:"导出备份"}),n.jsxs("label",{className:"secondary-button",children:["恢复备份",n.jsx("input",{type:"file",accept:"application/json,.json",disabled:k,onChange:v=>{const je=v.target.files?.[0];je&&Ft(je),v.target.value=""}})]})]})]})})}),M==="auth"&&n.jsx(lt,{title:"账号与注册",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"开放用户注册"}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:O?"启用":"关闭"}),n.jsx("button",{type:"button",className:O?"ios-switch is-on":"ios-switch","aria-label":O?"关闭用户注册":"开放用户注册","aria-pressed":!!O,onClick:He,children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:"注册方式"}),n.jsx("div",{className:"registration-mode-control",role:"group","aria-label":"注册方式",children:[{value:"username",label:"账号密码"},{value:"email",label:"邮箱"},{value:"discord",label:"Discord"}].map(v=>n.jsx("button",{type:"button",className:L===v.value?"selected":"",onClick:()=>Qe(O??!0,v.value),children:v.label},v.value))})]}),n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["新用户初始额度",n.jsx("small",{children:"注册完成后自动发放,仅影响之后的新用户"})]}),n.jsxs("div",{className:"setting-value auth-default-balance",children:[n.jsx("input",{type:"number",min:"0",step:"0.01",value:z,onChange:v=>g(v.target.value),"aria-label":"新用户初始额度"}),n.jsx("button",{type:"button",className:"secondary-button",onClick:()=>Qe(O,L,Number(z)),children:"保存"})]})]})]})}),M==="check-in"&&n.jsx(lt,{title:"每日签到奖励",children:n.jsxs("div",{className:"settings-group",children:[n.jsxs("div",{className:"setting",children:[n.jsxs("span",{children:["开放每日签到",n.jsx("small",{children:"用户每天可领取一次随机额度,按北京时间刷新"})]}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:q.enabled?"启用":"关闭"}),n.jsx("button",{type:"button",className:q.enabled?"ios-switch is-on":"ios-switch","aria-label":q.enabled?"关闭每日签到":"开放每日签到","aria-pressed":q.enabled,onClick:()=>_(v=>({...v,enabled:!v.enabled})),children:n.jsx("span",{})})]})]}),n.jsxs("div",{className:"setting check-in-settings-row",children:[n.jsxs("span",{children:["随机奖励范围",n.jsx("small",{children:"领取金额精确到 0.01,直接计入用户余额和额度流水"})]}),n.jsxs("div",{className:"check-in-reward-inputs",children:[n.jsxs("label",{children:[n.jsx("span",{children:"最低"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:q.minReward,onChange:v=>_(je=>({...je,minReward:Number(v.target.value)}))})]}),n.jsxs("label",{children:[n.jsx("span",{children:"最高"}),n.jsx("input",{type:"number",min:"0.01",max:"1000000",step:"0.01",value:q.maxReward,onChange:v=>_(je=>({...je,maxReward:Number(v.target.value)}))})]})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:y}),n.jsx("button",{type:"button",className:"primary-button",disabled:k,onClick:dt,children:k?"保存中":"保存签到设置"})]})]})}),M==="admin"&&n.jsx(lt,{title:"管理员账号",children:n.jsxs("form",{className:"discord-settings",onSubmit:v=>{v.preventDefault(),Je()},children:[n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"登录账号"}),n.jsx("input",{value:ge,onChange:v=>re(v.target.value),autoComplete:"username"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"显示名称"}),n.jsx("input",{value:Ne,onChange:v=>$(v.target.value),autoComplete:"name"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"邮箱"}),n.jsx("input",{type:"email",value:ve,onChange:v=>U(v.target.value),autoComplete:"email"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Discord 用户 ID(可选)"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:F,onChange:v=>ce(v.target.value),placeholder:se?.discordUserId?"已绑定":"输入管理员的 Discord 用户 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"当前密码"}),n.jsx("input",{type:"password",value:xe,onChange:v=>Te(v.target.value),autoComplete:"current-password",placeholder:"修改密码时填写"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"新密码"}),n.jsx("input",{type:"password",value:ae,onChange:v=>Q(v.target.value),autoComplete:"new-password",placeholder:"留空表示不修改"})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:y}),n.jsx("button",{className:"primary-button",type:"submit",children:"保存账号"})]})]})}),M==="discord"&&n.jsx(lt,{title:"Discord 登录",children:p?n.jsxs("form",{className:"discord-settings",autoComplete:"off",onSubmit:v=>{v.preventDefault(),V()},children:[n.jsxs("div",{className:"discord-toggle-row",children:[n.jsxs("div",{children:[n.jsx("strong",{children:"Discord 登录"}),n.jsx("span",{children:p.enabled?"已启用":"未启用"})]}),n.jsx("button",{type:"button",className:p.enabled?"ios-switch is-on":"ios-switch","aria-label":p.enabled?"停用 Discord 登录":"启用 Discord 登录","aria-pressed":p.enabled,onClick:()=>r({...p,enabled:!p.enabled}),children:n.jsx("span",{})})]}),n.jsxs("div",{className:"settings-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"Client ID"}),n.jsx("input",{inputMode:"numeric",autoComplete:"off",value:p.clientId,onChange:v=>r({...p,clientId:v.target.value}),placeholder:"100000000000000001"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"Client Secret"}),n.jsx("input",{type:"password",autoComplete:"new-password",value:me,onChange:v=>Z(v.target.value),placeholder:p.clientSecretSet?"已设置,留空表示不修改":"粘贴 Discord Client Secret"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"回调地址"}),n.jsx("input",{type:"url",value:p.redirectUri,onChange:v=>r({...p,redirectUri:v.target.value}),placeholder:"https://你的域名/api/auth/discord/callback"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"服务器 ID"}),n.jsx("input",{inputMode:"numeric",value:p.allowedGuildId,onChange:v=>r({...p,allowedGuildId:v.target.value}),placeholder:"允许登录的服务器 ID"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"身份组 ID"}),n.jsx("input",{inputMode:"numeric",value:p.allowedRoleId,onChange:v=>r({...p,allowedRoleId:v.target.value}),placeholder:"允许登录的身份组 ID"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"拉黑服务器 ID"}),n.jsx("textarea",{value:C,onChange:v=>Y(v.target.value),placeholder:"每行一个服务器 ID;命中的用户禁止注册 / 登录",rows:3}),n.jsx("small",{children:"用户若加入了这些 Discord 服务器中的任意一个,将无法注册或登录(优先于上面的允许规则)。"})]}),n.jsxs("label",{className:"settings-form-wide",children:[n.jsx("span",{children:"登录成功跳转地址"}),n.jsx("input",{type:"url",value:p.authSuccessUrl,onChange:v=>r({...p,authSuccessUrl:v.target.value}),placeholder:"https://你的域名/"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"登录有效期(小时)"}),n.jsx("input",{type:"number",min:"1",max:"8760",value:p.sessionTtlHours,onChange:v=>r({...p,sessionTtlHours:Number(v.target.value)})})]})]}),n.jsxs("div",{className:"settings-save-row",children:[n.jsx("span",{role:"status",children:y}),n.jsx("button",{className:"primary-button",type:"submit",disabled:k,children:k?"保存中":"保存配置"})]})]}):n.jsx("div",{className:"empty",children:"正在读取配置"})})]})}function nl({label:c,value:m}){return n.jsxs("div",{className:"metric",children:[n.jsx("span",{children:c}),n.jsx("strong",{children:m})]})}function wp({groups:c,onCreate:m,onUpdate:p,onDelete:r}){const[O,R]=x.useState(""),[L,P]=x.useState(""),[z,g]=x.useState(!1);async function q(_){if(_.preventDefault(),!!O.trim()){g(!0);try{await m({name:O.trim(),description:L.trim()}),R(""),P("")}finally{g(!1)}}}return n.jsxs("section",{className:"models-page",children:[n.jsxs(lt,{title:"用户分组",children:[n.jsxs("form",{className:"channel-create-form",onSubmit:q,children:[n.jsxs("div",{className:"channel-form-grid",children:[n.jsxs("label",{children:[n.jsx("span",{children:"分组名称"}),n.jsx("input",{value:O,onChange:_=>R(_.target.value),placeholder:"例如 尊享用户 / 试用用户"})]}),n.jsxs("label",{children:[n.jsx("span",{children:"说明"}),n.jsx("input",{value:L,onChange:_=>P(_.target.value),placeholder:"可选"})]})]}),n.jsx("div",{className:"channel-card-actions",children:n.jsx("button",{className:"primary-button",type:"submit",disabled:z||!O.trim(),children:z?"创建中":"创建分组"})})]}),n.jsx("p",{className:"muted-inline",children:"分组用于控制渠道对用户的可见范围:把用户归入分组,并在渠道上勾选「可见分组」即可限制访问。未分组的用户只能使用未限制分组的渠道。"})]}),n.jsx(lt,{title:"全部分组",children:c.length===0?n.jsx(qt,{text:"还没有分组"}):n.jsx("div",{className:"channels-stack",children:c.map(_=>n.jsx(Bp,{group:_,onUpdate:p,onDelete:r},_.id))})})]})}function Bp({group:c,onUpdate:m,onDelete:p}){const[r,O]=x.useState(!1),[R,L]=x.useState(c.name),[P,z]=x.useState(c.description),[g,q]=x.useState(!1);async function _(){q(!0);try{await m(c.id,{name:R.trim(),description:P.trim()}),O(!1)}finally{q(!1)}}return n.jsx("div",{className:"channel-card",children:n.jsxs("div",{className:"channel-card-head",children:[n.jsx("div",{children:r?n.jsxs("div",{className:"group-edit-fields",children:[n.jsx("input",{value:R,onChange:ee=>L(ee.target.value),placeholder:"分组名称"}),n.jsx("input",{value:P,onChange:ee=>z(ee.target.value),placeholder:"说明"})]}):n.jsxs(n.Fragment,{children:[n.jsx("strong",{children:c.name}),c.description&&n.jsx("span",{children:c.description}),n.jsxs("small",{children:["创建于 ",Wt(c.createdAt)]})]})}),n.jsx("div",{className:"channel-card-head-actions",children:r?n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"primary-button compact-button",onClick:_,disabled:g||!R.trim(),children:g?"保存中":"保存"}),n.jsx("button",{className:"secondary-button compact-button",onClick:()=>{L(c.name),z(c.description),O(!1)},children:"取消"})]}):n.jsxs(n.Fragment,{children:[n.jsx("button",{className:"secondary-button compact-button",onClick:()=>O(!0),children:"重命名"}),n.jsx("button",{className:"danger-button compact-button",onClick:()=>p(c.id),children:"删除"})]})})]})})}function lt({title:c,children:m}){return n.jsxs("section",{className:"panel",children:[n.jsx("div",{className:"panel-title",children:n.jsx("h2",{children:c})}),m]})}function zt({tone:c,children:m}){return n.jsx("span",{className:`badge tone-${c}`,children:m})}function $t({label:c,value:m,switchOn:p}){return n.jsxs("div",{className:"setting",children:[n.jsx("span",{children:c}),n.jsxs("div",{className:"setting-value",children:[n.jsx("strong",{children:m}),typeof p=="boolean"&&n.jsx("div",{className:p?"ios-switch is-on":"ios-switch","aria-hidden":"true",children:n.jsx("span",{})})]})]})}function qp({value:c,options:m,onChange:p}){return n.jsx("div",{className:"segmented-control",children:m.map(r=>n.jsx("button",{className:c===r.value?"selected":"",onClick:()=>p(r.value),children:r.label},r.value))})}function qt({text:c}){return n.jsx("div",{className:"empty",children:c})}k0.createRoot(document.getElementById("root")).render(n.jsx(G0.StrictMode,{children:n.jsx(op,{})})); diff --git a/dist/assets/index-BvkROHFS.css b/dist/assets/index-ssd4aOT1.css similarity index 62% rename from dist/assets/index-BvkROHFS.css rename to dist/assets/index-ssd4aOT1.css index 4f33649..35182e8 100644 --- a/dist/assets/index-BvkROHFS.css +++ b/dist/assets/index-ssd4aOT1.css @@ -1 +1 @@ -:root{color:#1d1d1f;background:#f2f2f7;font-family:-apple-system,BlinkMacSystemFont,SF Pro Display,Segoe UI,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}*{box-sizing:border-box}body{margin:0;min-width:320px;min-height:100vh}button,input,select,textarea{font:inherit}button{border:0}.app-shell select:not([multiple]){appearance:none;padding-right:38px!important;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%)!important;background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%!important;background-size:5px 5px,5px 5px!important;background-repeat:no-repeat!important;cursor:pointer}.app-shell[data-theme=dark] select{color-scheme:dark}.app-shell[data-theme=dark] select option{color:#f5f5f7;background:#2c2c2e}.app-shell input[type=datetime-local],.app-shell input[type=date],.app-shell input[type=time]{color-scheme:dark}.app-shell input[type=datetime-local]::-webkit-calendar-picker-indicator,.app-shell input[type=date]::-webkit-calendar-picker-indicator,.app-shell input[type=time]::-webkit-calendar-picker-indicator{opacity:.72;cursor:pointer}.app-shell input[type=number]{appearance:textfield}.app-shell input[type=number]::-webkit-inner-spin-button,.app-shell input[type=number]::-webkit-outer-spin-button{margin:0;appearance:none}.app-shell{--bg: #f2f2f7;--surface: rgba(255, 255, 255, .78);--surface-solid: #ffffff;--group: #f4f5f7;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .12);--hairline-strong: rgba(60, 60, 67, .2);--blue: #007aff;--green: #34c759;--red: #ff3b30;--orange: #ff9500;--teal: #30b0c7;--shadow: 0 2px 8px rgba(0, 0, 0, .04), 0 12px 32px rgba(0, 0, 0, .06);--shadow-lg: 0 4px 12px rgba(0, 0, 0, .05), 0 20px 48px rgba(0, 0, 0, .1);--row-height: 58px;display:grid;grid-template-columns:264px 1fr;min-height:100vh;color:var(--text);background:var(--bg)}.app-shell[data-theme=dark]{--bg: #0a0a0c;--surface: rgba(22, 22, 26, .8);--surface-solid: #161618;--group: rgba(255, 255, 255, .04);--text: #f5f5f7;--muted: #8e8e93;--hairline: rgba(255, 255, 255, .06);--hairline-strong: rgba(255, 255, 255, .1);--shadow: 0 2px 8px rgba(0, 0, 0, .2), 0 12px 32px rgba(0, 0, 0, .25);--shadow-lg: 0 4px 12px rgba(0, 0, 0, .3), 0 24px 56px rgba(0, 0, 0, .4);background:var(--bg);color-scheme:dark}.app-shell[data-density=compact]{--row-height: 48px}.sidebar{position:sticky;top:0;height:100vh;padding:16px 14px;background:var(--surface-solid);border-right:1px solid var(--hairline);box-shadow:2px 0 12px #00000008}.app-shell[data-theme=dark] .sidebar{background:#111113;border-right-color:#ffffff0d;box-shadow:2px 0 16px #00000040}.ios-window-dots{display:flex;gap:7px;padding:4px 10px 18px;cursor:default}.ios-window-dots span{width:12px;height:12px;border-radius:50%;opacity:.85;transition:opacity .16s ease,transform .16s ease}.ios-window-dots:hover span{opacity:1}.ios-window-dots span:hover{transform:scale(1.18)}.ios-window-dots span:nth-child(1){background:#ff5f57}.ios-window-dots span:nth-child(2){background:#ffbd2e}.ios-window-dots span:nth-child(3){background:#28c840}.brand{display:flex;align-items:center;gap:12px;padding:0 10px 24px}.brand-mark{display:grid;place-items:center;width:42px;height:42px;color:#fff;background:#1d1d1f;border-radius:13px;font-weight:800;box-shadow:inset 0 1px #ffffff2e}.app-shell[data-theme=dark] .brand-mark{color:#fff;background:#76768033;border:0}.brand strong,.brand span{display:block}.brand span{margin-top:2px;color:var(--muted);font-size:13px}nav{display:grid;gap:6px}.nav-item{position:relative;display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:0 12px;color:var(--muted);background:transparent;border-radius:12px;cursor:pointer;text-align:left}.nav-item:hover{color:var(--text);background:var(--group)}.nav-item.active{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000000f,inset 0 0 0 1px var(--hairline)}.app-shell[data-theme=dark] .nav-item:hover{background:#ffffff0d}.app-shell[data-theme=dark] .nav-item.active{color:#fff;background:#ffffff14;box-shadow:0 1px 6px #0003,inset 0 0 0 1px #ffffff0f}.sidebar-footer{position:absolute;left:14px;right:14px;bottom:16px;display:flex;justify-content:space-between;align-items:center;min-height:44px;padding:0 12px;color:var(--muted);background:var(--group);border-radius:14px;font-size:13px}.sidebar-footer strong{display:inline-flex;align-items:center;gap:7px;color:var(--green)}.sidebar-footer .pulse-dot{width:7px;height:7px}.icon{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:0 0 auto}.content{width:calc(100vw - 264px);padding:28px 30px 44px;background:var(--bg)}.topbar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;gap:18px;margin:-28px -30px 24px;padding:24px 30px 18px;background:color-mix(in srgb,var(--bg) 82%,transparent);border-bottom:1px solid var(--hairline);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.app-shell[data-theme=dark] .topbar{background:#000000d1;border-bottom-color:#ffffff14}.topbar-actions,.panel-toolbar,.setting-value{display:flex;align-items:center;gap:10px}.eyebrow{margin:0 0 5px;color:var(--muted);font-size:13px}h1,h2,h3,p{margin:0}h1{font-size:34px;line-height:1.08;letter-spacing:0}h2{font-size:18px;letter-spacing:0}h3{margin:6px 0 10px;font-size:14px;color:var(--muted)}.primary-button,.secondary-button,.danger-button,.icon-button,.theme-toggle{display:inline-flex;align-items:center;justify-content:center;min-height:38px;border-radius:999px;cursor:pointer;text-decoration:none}.primary-button{padding:0 18px;color:#fff;background:var(--blue);font-weight:700;box-shadow:0 2px 6px #007aff40;box-shadow:0 5px 14px color-mix(in srgb,var(--blue) 24%,transparent)}.secondary-button{padding:0 16px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline-strong);font-weight:650;box-shadow:0 1px 3px #0000000a}.danger-button{padding:0 16px;color:#d70015;background:color-mix(in srgb,var(--red) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--red) 28%,var(--hairline));font-weight:700}.compact-button{min-height:32px;padding:0 12px;font-size:13px}.icon-button{width:38px;color:var(--text);background:var(--group);border:1px solid var(--hairline)}.theme-toggle{gap:8px;padding:0 14px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline)}.app-shell[data-theme=dark] .secondary-button,.app-shell[data-theme=dark] .icon-button,.app-shell[data-theme=dark] .theme-toggle,.app-shell[data-theme=dark] .compact-button{background:#ffffff14;border-color:#ffffff1a;box-shadow:0 1px 4px #00000026}.primary-button:disabled,.secondary-button:disabled,.danger-button:disabled,.icon-button:disabled,.theme-toggle:disabled{cursor:not-allowed;opacity:.55}.muted-inline{color:var(--muted);font-size:13px}.status-button{display:inline-flex;justify-content:flex-start;padding:0;background:transparent;border:0;cursor:pointer}.segmented-control{display:inline-grid;grid-auto-flow:column;gap:2px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.app-shell[data-theme=dark] .segmented-control,.app-shell[data-theme=dark] .user-filter-row,.app-shell[data-theme=dark] .model-filter-actions,.app-shell[data-theme=dark] .log-status-filter,.app-shell[data-theme=dark] .settings-tabs,.app-shell[data-theme=dark] .registration-mode-control{background:#7676801f;border-color:transparent}.segmented-control button{min-width:54px;height:30px;padding:0 12px;color:var(--muted);background:transparent;border-radius:999px;cursor:pointer}.segmented-control button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.app-shell[data-theme=dark] .segmented-control button.selected,.app-shell[data-theme=dark] .user-filter-row button.selected,.app-shell[data-theme=dark] .model-filter-actions button.selected,.app-shell[data-theme=dark] .log-status-filter button.selected,.app-shell[data-theme=dark] .settings-tabs button.selected,.app-shell[data-theme=dark] .registration-mode-control button.selected{background:#ffffff1f;box-shadow:none}.page-stack{display:grid;gap:18px}.hero-strip{display:flex;align-items:center;justify-content:space-between;gap:18px;min-height:128px;padding:24px;background:var(--surface);border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.hero-strip span,.metric span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.hero-strip strong{display:block;font-size:22px;letter-spacing:0}.hero-strip p{max-width:620px;margin-top:8px;color:var(--muted);line-height:1.55}.live-island{display:inline-flex;align-items:center;gap:8px;min-width:92px;height:34px;padding:0 14px;color:#fff;background:#1d1d1f;border:1px solid var(--hairline);border-radius:999px;font-weight:700;box-shadow:inset 0 1px #ffffff29}.app-shell[data-theme=dark] .live-island{color:var(--muted);background:var(--group)}.hero-strip .live-island{margin-right:4px}.pulse-dot{width:9px;height:9px;background:var(--green);border-radius:50%;box-shadow:0 0 0 5px color-mix(in srgb,var(--green) 20%,transparent);animation:status-pulse 1.8s ease-out infinite}.quick-actions{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.quick-action{display:flex;align-items:center;justify-content:center;gap:9px;min-height:48px;padding:0 14px;color:var(--text);background:var(--surface);border:1px solid var(--hairline);border-radius:999px;cursor:pointer;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.quick-action:nth-child(1){color:var(--blue)}.quick-action:nth-child(2){color:var(--teal)}.quick-action:nth-child(3){color:var(--green)}.quick-action:nth-child(4){color:var(--orange)}.metrics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}.metric,.panel{background:var(--surface-solid);border:1px solid var(--hairline);box-shadow:var(--shadow)}.app-shell[data-theme=dark] .quick-action,.app-shell[data-theme=dark] .metric,.app-shell[data-theme=dark] .panel,.app-shell[data-theme=dark] .hero-strip,.app-shell[data-theme=dark] .flow-panel,.app-shell[data-theme=dark] .model-hero{background:var(--surface-solid);border-color:var(--hairline);box-shadow:var(--shadow)}.metric{min-height:118px;padding:18px;border-radius:22px}.metric strong{display:block;overflow:hidden;font-size:31px;letter-spacing:0;text-overflow:ellipsis;white-space:nowrap}.split-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.flow-panel{display:grid;grid-template-columns:minmax(190px,.7fr) minmax(0,1.3fr);gap:18px;align-items:center;padding:18px;background:var(--surface);border:1px solid var(--hairline);border-radius:24px;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.flow-copy span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.flow-copy strong{display:block;font-size:20px;line-height:1.3}.flow-steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.flow-step{position:relative;min-height:104px;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.flow-step:not(:last-child):after{content:"";position:absolute;top:50%;right:-10px;width:10px;height:1px;background:var(--hairline-strong)}.flow-index{display:grid;place-items:center;width:28px;height:28px;margin-bottom:12px;color:#fff;background:var(--blue);border-radius:50%;font-size:13px;font-weight:800}.flow-step strong,.flow-step span{display:block}.flow-step span{margin-top:4px;color:var(--muted);font-size:13px}.panel{padding:20px;border-radius:20px;min-width:0}.app-shell[data-theme=dark] .panel{border-radius:18px}.panel-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding:0 2px}.panel-title h2{font-size:17px;font-weight:700}.app-shell[data-theme=dark] .panel-title{padding-bottom:14px;border-bottom:1px solid rgba(255,255,255,.06)}.list-row,.setting{display:flex;align-items:center;justify-content:space-between;gap:14px;min-height:var(--row-height);padding:10px 2px;border-top:1px solid var(--hairline)}.list-row:first-of-type,.setting:first-child{border-top:0}.list-row>div,.setting>div{min-width:0}.row-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:8px;flex-shrink:0}.list-row strong,.list-row span,.setting span,.setting strong,.table-row span,.table-row strong,.table-row small{min-width:0}.list-row strong,.list-row span{display:block}.list-row span,.table-row small{margin-top:3px;color:var(--muted);font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.overview-channel-row>div{flex:1 1 auto;overflow:hidden}.overview-channel-row>.badge{flex:0 0 auto;min-width:54px;overflow:visible}.badge{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:54px;height:27px;padding:0 11px;color:var(--muted);background:var(--group);border-radius:999px;font-size:12px;font-weight:650;letter-spacing:.01em;white-space:nowrap}.app-shell[data-theme=dark] .badge{background:#76768024;border:0}.badge.tone-active:before,.badge.tone-healthy:before,.badge.tone-available:before,.badge.tone-success:before,.badge.tone-disabled:before,.badge.tone-failed:before,.badge.tone-limited:before,.badge.tone-overdue:before,.badge.tone-standby:before{content:"";display:inline-block;width:5px;height:5px;border-radius:50%;background:currentColor;flex:0 0 auto}.tone-active,.tone-healthy,.tone-available,.tone-success{color:#118446;background:color-mix(in srgb,var(--green) 16%,transparent)}.tone-disabled,.tone-failed{color:#d70015;background:color-mix(in srgb,var(--red) 14%,transparent)}.tone-limited,.tone-overdue,.tone-standby{color:#a05a00;background:color-mix(in srgb,var(--orange) 15%,transparent)}.users-layout{display:grid;grid-template-columns:minmax(780px,1.55fr) minmax(380px,.7fr);gap:18px;align-items:start}.users-layout .panel:first-child{padding:14px}.users-layout .panel:first-child .table{background:transparent;border:0;border-radius:0;gap:8px}.users-layout .panel:first-child .table-head{min-height:34px;padding:0 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-head{background:#7676801a;border-color:transparent}.users-layout .panel:first-child .table-row{min-height:56px;padding:0 14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:16px}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row{background:#1c1c1ec7;border-color:#ffffff0d}.users-layout .panel:first-child .table-row:hover{background:var(--group)}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row:hover{background:#2c2c2ee0}.users-layout .panel:first-child .table-row.selected{border-color:color-mix(in srgb,var(--blue) 45%,var(--hairline));box-shadow:inset 3px 0 0 var(--blue)}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row.selected{background:#76768029;border-color:transparent;box-shadow:none}.user-summary-strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:12px}.user-summary-strip span{min-height:50px;padding:10px 12px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:14px;font-size:13px}.user-summary-strip strong{display:block;color:var(--text);font-size:20px}.user-filter-row{display:flex;gap:4px;width:fit-content;margin-bottom:12px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.user-filter-row button{min-height:30px;padding:0 13px;color:var(--muted);background:transparent;border-radius:999px;cursor:pointer;font-weight:700}.user-filter-row button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.mobile-bulk-select{display:none;margin-bottom:12px}.bulk-action-bar{display:grid;grid-template-columns:auto 100px minmax(160px,1fr) auto auto auto;align-items:center;gap:8px;margin-bottom:12px;padding:10px;background:color-mix(in srgb,var(--blue) 8%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 25%,var(--hairline));border-radius:12px}.bulk-action-bar input,.auth-default-balance input{min-width:0;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.bulk-action-bar input:focus,.auth-default-balance input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.pagination-bar{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:12px;color:var(--muted);font-weight:700}.models-page{display:grid;gap:18px;width:100%}.model-hero{padding:18px 22px;background:var(--surface);border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.model-hero span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.model-hero strong{display:block;font-size:24px;line-height:1.3}.model-hero p{margin-top:8px;color:var(--muted)}.model-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.model-list{display:grid;gap:10px}.model-list-toolbar{justify-content:space-between;align-items:center}.model-list-toolbar input{flex:1 1 460px;width:auto;max-width:720px;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-list-toolbar input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-filter-actions{display:inline-flex;gap:6px;padding:4px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.model-filter-actions button{height:32px;padding:0 12px;color:var(--muted);background:transparent;border:0;border-radius:999px}.model-filter-actions button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.model-provider-filter{display:flex;gap:8px;margin:14px 0;padding-bottom:2px;overflow-x:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 45%,transparent) transparent}.model-provider-filter button{display:grid;grid-template-columns:34px minmax(0,1fr) auto;align-items:center;gap:10px;flex:0 0 240px;min-height:58px;padding:10px;color:var(--text);text-align:left;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.model-provider-filter button.selected{background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 46%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 28%,transparent)}.app-shell[data-theme=dark] .model-provider-filter button.selected,.app-shell[data-theme=dark] .provider-chip-grid button.selected,.app-shell[data-theme=dark] .stream-mode-grid button.selected{background:#ffffff1f;border-color:transparent;box-shadow:none}.model-provider-filter strong,.model-provider-filter small{display:block;min-width:0}.model-provider-filter strong{overflow-wrap:anywhere}.model-provider-filter small{color:var(--muted);font-weight:800}.provider-icon-all{display:grid;place-items:center;flex:0 0 38px;width:38px;height:38px;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.02em;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 26%,var(--hairline));border-radius:10px}.model-list-summary{display:inline-flex;align-items:baseline;gap:6px;margin-bottom:10px;color:var(--muted);font-size:13px}.model-list-summary strong{color:var(--text);font-size:20px}.model-provider-groups{display:grid;gap:14px}.model-provider-group{overflow:hidden;border:1px solid var(--hairline);border-radius:14px}.model-provider-group>header{display:flex;align-items:center;gap:10px;min-height:58px;padding:9px 12px;background:var(--group);border-bottom:1px solid var(--hairline)}.model-provider-group>header div{display:grid;gap:2px}.model-provider-group>header span{color:var(--muted);font-size:12px}.provider-icon,.provider-icon svg{display:block;width:38px;height:38px;flex:0 0 38px}.provider-icon svg rect{fill:var(--surface-solid);stroke:var(--hairline)}.provider-icon svg text{fill:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:17px;font-weight:800}.provider-icon svg path{fill:currentColor}.provider-icon-google svg text{fill:#4285f4}.provider-icon-openai{color:var(--text)}.provider-icon-deepseek,.provider-icon-deepseek svg,.provider-icon-deepseek svg path{color:#4d6bfe;fill:#4d6bfe}.provider-icon-openrouter svg text{fill:#ef4444}.provider-icon-groq svg text{fill:#f55036}.provider-icon-moonshot svg text{fill:#16a34a}.model-compact-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(560px,1fr))}.model-compact-row{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;gap:9px;min-width:0;min-height:78px;padding:12px;border-bottom:1px solid var(--hairline)}.model-compact-row:last-child{border-bottom:0}.model-compact-main{min-width:0}.model-compact-main strong,.model-compact-main small{display:block;min-width:0;overflow-wrap:anywhere}.model-compact-main small{margin-top:3px;color:var(--muted);font-size:12px;line-height:1.35}.model-compact-main span{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px}.model-compact-main em{max-width:120px;overflow:hidden;padding:3px 7px;color:var(--muted);font-size:11px;font-style:normal;text-overflow:ellipsis;white-space:nowrap;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:999px}.model-row-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0;flex-wrap:wrap}.model-row-actions .compact-button{min-height:32px;padding-inline:11px}.model-row-actions{gap:6px}.model-row-actions .icon-button{width:32px;min-height:32px;color:var(--muted);background:transparent;border-color:transparent}.model-recommended-mark{padding:4px 8px;color:var(--orange);background:color-mix(in srgb,var(--orange) 10%,transparent);border-radius:999px;font-size:11px;font-weight:700}.model-row-menu{position:relative}.model-row-menu>summary{width:32px;min-height:32px;color:var(--muted);line-height:27px;text-align:center;letter-spacing:1px;list-style:none;background:transparent;border:1px solid transparent;border-radius:10px;cursor:pointer}.model-row-menu>summary::-webkit-details-marker{display:none}.model-row-menu>summary:hover{color:var(--text);background:var(--group)}.model-row-menu>div{position:absolute;right:0;bottom:calc(100% + 6px);z-index:8;display:grid;width:max-content;gap:2px;padding:6px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:var(--shadow)}.model-row-menu button{min-height:34px;padding:0 10px;color:var(--text);text-align:left;background:transparent;border:0;border-radius:8px;cursor:pointer;font-size:13px}.model-row-menu button:hover{background:var(--group)}.model-row-menu button.is-danger{color:var(--red)}.model-row-menu button.is-danger:hover{background:color-mix(in srgb,var(--red) 10%,var(--surface-solid))}.settings-tabs{display:flex;flex-wrap:wrap;width:fit-content;max-width:100%;padding:4px;gap:2px;overflow-x:auto;background:var(--group);border-radius:14px}.settings-tabs button{display:inline-flex;flex:0 0 auto;align-items:center;min-height:34px;padding:0 12px;border-radius:10px}.settings-tabs button small{display:none}.settings-tab-note{display:flex;align-items:baseline;gap:8px;min-height:18px;color:var(--muted);font-size:13px}.settings-tab-note strong{color:var(--text);font-size:14px}.logs-table{grid-template-columns:minmax(280px,1.55fr) minmax(220px,1fr) minmax(180px,.9fr) 82px}.logs-layout{display:block}.log-entry .table-row{min-height:58px}.log-entry .table-row>span:nth-child(2),.log-entry .table-row>span:nth-child(3){overflow:hidden;color:var(--muted);text-overflow:ellipsis;white-space:nowrap}.log-inspector{position:relative;top:auto;grid-template-columns:minmax(220px,.8fr) minmax(0,1.6fr) auto;align-items:start;margin-top:14px;padding:16px;border-radius:16px}.log-inspector header{padding:6px 14px 6px 0;border-right:1px solid var(--hairline);border-bottom:0}.log-detail{grid-template-columns:repeat(4,minmax(0,1fr))}.log-detail>div{padding:9px 10px;border-radius:10px}.log-actions{align-self:center;justify-content:flex-end}@media(max-width:980px){.log-inspector{grid-template-columns:1fr}.log-inspector header{padding:0 0 12px;border-right:0;border-bottom:1px solid var(--hairline)}.log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}}.logs-layout.has-detail{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(360px,.75fr);gap:14px;align-items:start}.logs-layout.has-detail .log-inspector{position:sticky;top:92px;display:grid;grid-template-columns:1fr;margin-top:0;padding:16px}.logs-layout.has-detail .log-inspector header{padding:0 0 12px;border-right:0;border-bottom:1px solid var(--hairline)}.logs-layout.has-detail .log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:980px){.logs-layout.has-detail{grid-template-columns:1fr}.logs-layout.has-detail .log-inspector{position:static}}@media(max-width:720px){.settings-tabs{flex-wrap:nowrap;width:100%}.settings-tab-note{align-items:flex-start;flex-direction:column;gap:2px}}.pager{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:12px}.pager span{color:var(--muted);font-size:13px;font-weight:700}.model-create-form{display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) auto;gap:10px;align-items:center}.model-create-form input,.model-create-form select{width:100%;min-width:0;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-create-form select{appearance:none}.model-create-form input:focus,.model-create-form select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-create-wide{grid-column:span 2}.model-create-message{grid-column:1 / -1;min-height:18px;color:#ff3b30;font-size:13px}.drawing-channel-models{display:flex;flex-wrap:wrap;gap:8px}.drawing-channel-models span{max-width:100%;padding:7px 10px;color:var(--muted);font-size:12px;font-weight:750;background:var(--group);border:1px solid var(--hairline);border-radius:999px;overflow-wrap:anywhere}.model-card{display:grid;gap:12px;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.model-card.featured{min-height:210px}.model-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.model-card-head strong,.model-card-head span{display:block}.model-card-head span{margin-top:4px;color:var(--muted);font-size:13px}.model-card p{color:var(--muted);line-height:1.55}.model-card-actions{display:flex;justify-content:flex-end;gap:8px}.alias-row,.model-meta{display:flex;flex-wrap:wrap;gap:8px}.alias-row span,.model-meta span{display:inline-flex;align-items:center;min-height:28px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px;font-weight:700}.model-meta span{color:var(--muted);font-weight:650}.model-id{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:42px;padding:0 0 0 12px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.model-id code{overflow:hidden;color:var(--text);text-overflow:ellipsis;white-space:nowrap}.panel-toolbar{margin-bottom:12px}.search-box{display:flex;align-items:center;gap:8px;width:100%;height:42px;padding:0 13px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px}.app-shell[data-theme=dark] .search-box,.app-shell[data-theme=dark] .model-list-toolbar input,.app-shell[data-theme=dark] .model-create-form input,.app-shell[data-theme=dark] .model-create-form select,.app-shell[data-theme=dark] .channel-form-grid input,.app-shell[data-theme=dark] .channel-form-grid textarea,.app-shell[data-theme=dark] .channel-editor input,.app-shell[data-theme=dark] .provider-picker-trigger,.app-shell[data-theme=dark] .key-editor-grid input,.app-shell[data-theme=dark] .settings-form-grid input,.app-shell[data-theme=dark] .settings-form-grid textarea,.app-shell[data-theme=dark] .maintenance-control input,.app-shell[data-theme=dark] .bulk-action-bar input,.app-shell[data-theme=dark] .auth-default-balance input{background:#7676801f;border-color:transparent}.search-box input{width:100%;border:0;outline:0;background:transparent;color:var(--text)}.search-box input::placeholder{color:var(--muted)}.table{display:grid;overflow:hidden;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .table{background:#1c1c1eb8;border-color:#ffffff0d}.table:has(.channel-editor){overflow:visible}.table-head,.table-row{display:grid;gap:12px;align-items:center;min-height:var(--row-height);padding:0 14px;text-align:left}.table-head{color:var(--muted);font-size:12px;font-weight:700;background:var(--group);border-bottom:1px solid var(--hairline)}.app-shell[data-theme=dark] .table-head{background:#7676801a;border-bottom-color:#ffffff0d}.table-row{width:100%;color:var(--text);background:transparent;border-bottom:1px solid var(--hairline)}.app-shell[data-theme=dark] .table-row{border-bottom-color:#ffffff0d}.table-row small{display:block}.table-row:last-child{border-bottom:0}button.table-row{cursor:pointer}button.table-row:hover{background:var(--group)}.app-shell[data-theme=dark] button.table-row:hover,.app-shell[data-theme=dark] .log-entry .table-row:hover,.app-shell[data-theme=dark] .log-entry .table-row.selected{background:#7676801f}.users-table{grid-template-columns:22px minmax(220px,1fr) 86px minmax(120px,.45fr) 68px}.users-table>span:nth-child(4),.users-table>span:nth-child(5){justify-self:end;text-align:right}.users-table.table-row>span:nth-child(4){max-width:100%;overflow:hidden;font-variant-numeric:tabular-nums;text-overflow:ellipsis}.users-table>input[type=checkbox]{width:16px;height:16px;margin:0;accent-color:var(--blue);cursor:pointer}.channels-table{grid-template-columns:minmax(220px,1.4fr) 90px 64px minmax(150px,.8fr) minmax(240px,1fr)}.channels-stack{display:grid;gap:14px}.channel-create-form{margin-bottom:14px}.channel-create-form .channel-form-grid{grid-template-columns:1fr 1fr;gap:14px}.channel-create-form .channel-form-wide{grid-column:1 / -1}.channel-card{display:grid;gap:14px;padding:16px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .channel-card,.app-shell[data-theme=dark] .model-card,.app-shell[data-theme=dark] .log-inspector,.app-shell[data-theme=dark] .settings-group,.app-shell[data-theme=dark] .provider-picker-menu{background:#1c1c1eb8;border-color:#ffffff0f}.channel-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.channel-card-head>div:first-child{min-width:0}.channel-card-head-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;flex-shrink:0}.channel-card-head strong,.channel-card-head span{display:block}.channel-card-head span{margin-top:4px;color:var(--muted);font-size:13px}.channel-card-head small{display:block;max-width:100%;margin-top:6px;color:var(--muted);font-size:12px;line-height:1.45;overflow-wrap:anywhere}.provider-chip-grid{display:flex;flex-wrap:wrap;gap:8px}.provider-chip-grid button{min-height:34px;padding:0 12px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;cursor:pointer;font-weight:750}.provider-chip-grid button.selected{color:var(--text);background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 42%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 30%,transparent)}.stream-mode-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.stream-mode-grid button{display:grid;gap:3px;min-height:58px;padding:9px 11px;color:var(--muted);text-align:left;background:var(--group);border:1px solid var(--hairline);border-radius:14px;cursor:pointer}.stream-mode-grid button strong{color:var(--text);font-size:14px}.stream-mode-grid button span{overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.stream-mode-grid button.selected{background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 42%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 30%,transparent)}.app-shell[data-theme=dark] .provider-chip-grid button.selected,.app-shell[data-theme=dark] .stream-mode-grid button.selected{background:#ffffff1f;border-color:transparent;box-shadow:none}.channel-form-grid{display:grid;grid-template-columns:1.4fr .5fr .7fr;gap:12px}.channel-form-grid label{display:grid;min-width:0;gap:7px;color:var(--muted);font-size:13px;font-weight:700}.channel-model-field{display:grid;min-width:0;gap:7px}.field-label-row{display:flex;align-items:center;justify-content:space-between;gap:10px;color:var(--muted);font-size:13px;font-weight:700}.field-label-row small{font-size:12px;font-weight:700}.field-label-row .model-pull-button{min-height:28px;padding:0 12px;color:var(--blue);background:color-mix(in srgb,var(--blue) 10%,transparent);border:1px solid color-mix(in srgb,var(--blue) 26%,transparent);border-radius:999px;font-size:12.5px;font-weight:650;white-space:nowrap;cursor:pointer;transition:background .12s ease,transform .1s ease}.field-label-row .model-pull-button:hover{background:color-mix(in srgb,var(--blue) 16%,transparent)}.field-label-row .model-pull-button:active{transform:scale(.97)}.channel-form-wide{grid-column:span 2}.channel-billing-note{grid-column:1 / -1;color:var(--muted);font-size:12px}.channel-form-grid input,.channel-form-grid textarea{width:100%;min-width:0;min-height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.channel-form-grid textarea{min-height:72px;padding:10px 12px;resize:vertical;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.channel-form-grid input:focus,.channel-form-grid textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.channel-model-actions{display:flex;flex-wrap:wrap;gap:8px}.channel-card-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:10px}.channel-card-actions .model-create-message{flex:1;min-width:180px}.channel-editor{align-items:start;padding-block:12px}.channel-editor input,.provider-picker-trigger{width:100%;min-width:0;height:36px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.provider-picker{position:relative;z-index:2}.provider-picker-trigger{display:grid;grid-template-columns:minmax(0,1fr) 12px;align-items:center;gap:8px;text-align:left;cursor:pointer}.provider-picker-trigger span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.provider-picker-trigger i{width:7px;height:7px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:translateY(-2px) rotate(45deg)}.provider-picker-menu{position:absolute;top:calc(100% + 6px);left:0;display:grid;width:min(240px,70vw);max-height:280px;padding:6px;overflow:auto;background:color-mix(in srgb,var(--surface-solid) 94%,transparent);border:1px solid var(--hairline);border-radius:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.provider-picker-menu button{min-height:34px;padding:0 10px;color:var(--text);background:transparent;border-radius:9px;text-align:left;cursor:pointer}.provider-picker-menu button:hover,.provider-picker-menu button.selected{background:var(--group)}.provider-picker-menu button.selected{color:var(--blue);font-weight:800}.channel-editor strong{display:block;margin-bottom:8px}.channel-actions{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center}.logs-table{grid-template-columns:minmax(210px,1.35fr) minmax(170px,1fr) minmax(150px,.9fr) 78px 78px 86px 80px}.logs-layout{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(420px,.75fr);gap:14px;align-items:start}.logs-toolbar{display:grid;grid-template-columns:minmax(260px,1fr) auto auto;align-items:center;gap:12px;margin-bottom:14px}.log-status-filter{display:flex;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:10px}.log-status-filter button{min-height:32px;padding:0 12px;color:var(--muted);background:transparent;border-radius:7px;cursor:pointer}.log-status-filter button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 3px #0000001f}.log-entry+.log-entry{border-top:1px solid var(--hairline)}.log-entry .table-row{border:0;cursor:pointer}.log-entry .table-row:hover,.log-entry .table-row.selected{background:var(--group)}.log-inspector{position:sticky;top:92px;display:grid;gap:14px;min-width:0;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .flow-step{background:#7676801a;border-color:transparent}.log-inspector header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:12px;border-bottom:1px solid var(--hairline)}.log-inspector header div{display:grid;gap:4px;min-width:0}.log-inspector header span,.empty-inspector{color:var(--muted);font-size:13px}.app-shell[data-theme=dark] .sidebar-footer{background:#7676801f;border:0}.log-inspector header strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.empty-inspector{min-height:180px;place-items:center}.log-detail{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.log-detail>div{display:grid;gap:5px;min-width:0;padding:12px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.app-shell[data-theme=dark] .log-detail>div,.app-shell[data-theme=dark] .user-summary-strip span,.app-shell[data-theme=dark] .model-provider-group,.app-shell[data-theme=dark] .model-provider-filter button,.app-shell[data-theme=dark] .model-id,.app-shell[data-theme=dark] .alias-row span,.app-shell[data-theme=dark] .model-meta span{background:#7676801a;border-color:transparent}.log-detail span{color:var(--muted);font-size:12px}.log-detail strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.log-actions{display:flex;justify-content:flex-end;gap:8px}.detail-stack{display:grid;gap:14px}.user-hero{display:grid;grid-template-columns:52px 1fr auto;align-items:center;gap:12px;padding:4px 2px 16px;border-bottom:1px solid var(--hairline)}.user-hero h2{margin-bottom:3px;font-size:21px}.user-hero p{color:var(--muted);font-size:13px}.avatar{display:grid;place-items:center;width:52px;height:52px;color:#fff;background:var(--blue);border-radius:50%;font-weight:800;box-shadow:inset 0 1px #ffffff4d}.settings-group{overflow:hidden;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:16px;padding:4px 16px;box-shadow:0 1px 3px #0000000a}.app-shell[data-theme=dark] .settings-group{box-shadow:0 1px 2px #0003}.registration-mode-control{display:inline-grid;grid-auto-flow:column;gap:3px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.registration-mode-control button{min-width:74px;height:30px;padding:0 10px;color:var(--muted);background:transparent;border-radius:999px;font-weight:700;cursor:pointer}.registration-mode-control button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.settings-layout{display:grid;gap:20px}.settings-tabs{display:flex;flex-wrap:wrap;gap:6px;width:fit-content;max-width:100%;padding:5px;overflow-x:auto;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.settings-tabs button{display:flex;align-items:center;gap:6px;min-width:0;min-height:40px;padding:0 14px;color:var(--muted);text-align:left;background:transparent;border-radius:11px;cursor:pointer;transition:color .14s ease,background .14s ease,box-shadow .14s ease}.settings-tabs button:hover:not(.selected){color:var(--text);background:color-mix(in srgb,var(--surface-solid) 50%,transparent)}.settings-tabs button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.settings-tabs strong,.settings-tabs small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.settings-tabs strong{font-size:13px;font-weight:700}.settings-tabs small,.settings-tab-note{display:none}.discord-settings{display:grid;gap:18px}.discord-toggle-row,.settings-save-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.discord-toggle-row{min-height:56px;padding:0 2px 16px;border-bottom:1px solid var(--hairline)}.discord-toggle-row strong,.discord-toggle-row span{display:block}.discord-toggle-row span,.settings-save-row span{margin-top:3px;color:var(--muted);font-size:13px}.backup-actions label{display:inline-flex;align-items:center;cursor:pointer}.backup-actions input{display:none}.channel-import-actions{display:flex;align-items:center;flex-wrap:wrap;gap:10px}.channel-import-actions label{cursor:pointer}.channel-import-actions input,.channel-card-actions input[type=file]{display:none}.account-pool-list{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));margin-top:14px}.account-filter-bar{display:flex;flex-wrap:wrap;gap:7px;margin:10px 0 2px}.account-filter-bar button{padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--muted);cursor:pointer;font:inherit;font-size:12px}.account-filter-bar input{min-width:180px;flex:1 1 220px;padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--text);font:inherit;font-size:12px}.account-filter-bar select{padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--text);font:inherit;font-size:12px}.app-shell[data-theme=dark] .account-filter-bar select,.app-shell[data-theme=dark] .account-filter-bar input{background:#7676802e;border-color:#ffffff1a;color:#f5f5f7}.account-filter-bar button.selected{border-color:var(--accent);color:var(--accent)}.channel-capability-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}.channel-capability-tags span{padding:2px 7px;border:1px solid var(--hairline);border-radius:999px;color:var(--muted);font-size:11px}.account-pool-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:12px;padding:10px 12px;border:1px solid var(--hairline);border-radius:12px;background:var(--control)}.account-pool-main{display:grid;gap:8px;min-width:0}.account-pool-main>div{display:grid;gap:3px;min-width:0}.account-pool-title{display:flex;align-items:center;gap:8px;min-width:0}.account-pool-title strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-pool-main>div>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:12px}.account-pool-meta{display:flex;flex-shrink:0;align-items:center;gap:8px;justify-content:flex-end}.account-pool-more{display:flex;align-items:center;justify-content:space-between;gap:12px;grid-column:1 / -1;padding:6px 2px 0}.account-pool-more-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.account-pool-more-actions .secondary-button{flex-shrink:0}.quota-bars{display:grid;gap:6px}.quota-bar{display:grid;gap:4px}.quota-bar-label{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12px}.quota-bar-label strong{color:var(--text)}.quota-bar-track{height:5px;overflow:hidden;border-radius:999px;background:var(--hairline)}.quota-bar-track span{display:block;height:100%;border-radius:inherit;background:var(--green)}.key-editor{display:grid;gap:14px;padding:16px;border:1px solid var(--hairline);border-radius:22px;background:var(--surface-solid)}.app-shell[data-theme=dark] .key-editor{background:#1c1c1eb8;border-color:#ffffff0f}.key-editor+.key-editor{margin-top:12px}.key-editor-collapsible{gap:0;padding:0;overflow:hidden;border-radius:16px}.key-editor-collapsible[open]{gap:0}.key-editor-collapsible>summary{min-height:74px;padding:14px 16px;cursor:pointer;list-style:none}.key-editor-collapsible>summary::-webkit-details-marker{display:none}.key-editor-collapsible[open]>summary{border-bottom:1px solid var(--hairline)}.key-editor-body{display:grid;gap:14px;padding:16px}.key-expand-hint{padding:5px 10px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px}.key-editor-collapsible[open] .key-expand-hint:after{content:"中"}.key-editor-head{display:flex;align-items:center;justify-content:space-between;gap:16px}.key-editor-head strong,.key-editor-head span{display:block}.key-editor-head span{margin-top:4px;color:var(--muted);font-size:13px}.key-editor-grid{display:grid;grid-template-columns:minmax(160px,.8fr) minmax(240px,1.4fr) minmax(180px,1fr) minmax(140px,.8fr);gap:12px}.key-editor-grid label{display:grid;gap:7px;color:var(--muted);font-size:13px}.key-editor-grid input{width:100%;min-width:0;height:40px;padding:0 12px;color:var(--text);color-scheme:dark;background:var(--group);border:1px solid var(--hairline);border-radius:14px;outline:none}.key-editor-grid input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.key-editor-grid input::placeholder{color:var(--muted);opacity:.72}.key-editor-actions{display:flex;gap:8px;justify-content:flex-end}.settings-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.settings-form-grid label{display:grid;min-width:0;gap:7px;color:var(--muted);font-size:13px}.settings-form-grid input{width:100%;min-width:0;height:44px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.settings-form-grid input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-form-grid textarea{width:100%;min-width:0;min-height:88px;padding:10px 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none;resize:vertical;font:inherit;line-height:1.5;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.settings-form-grid textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-form-grid small{color:var(--muted);font-size:12px;line-height:1.45}.settings-form-grid input::placeholder{color:var(--muted);opacity:.72}.settings-form-wide{grid-column:1 / -1}.settings-save-row{min-height:44px}.settings-save-row .primary-button:disabled{cursor:wait;opacity:.58}.setting{min-height:52px}.setting span{color:var(--muted);font-size:14px}.setting-value{display:flex;align-items:center;gap:10px}.setting-value strong{color:var(--text);font-size:14px;font-weight:600}.setting>span small{display:block;margin-top:3px;color:var(--muted);font-size:12px}.auth-default-balance input{width:130px}.check-in-settings-row{align-items:center}.check-in-reward-inputs{display:grid;grid-template-columns:repeat(2,120px);gap:10px}.check-in-reward-inputs label{display:grid;gap:5px;color:var(--muted);font-size:12px}.check-in-reward-inputs input{width:100%;height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.check-in-reward-inputs input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.maintenance-control input{width:150px;height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.maintenance-control input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-save-row{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding-top:12px;border-top:1px solid var(--hairline)}.settings-save-row span{margin-right:auto;color:var(--muted);font-size:13px}.ios-switch{position:relative;flex:0 0 auto;width:49px;height:30px;padding:2px;background:#d1d1d6;border-radius:999px;cursor:pointer;transition:background .16s ease}.ios-switch span{display:block;width:26px;height:26px;margin:0;background:#fff;border-radius:50%;box-shadow:0 2px 5px #0000003d;transition:transform .16s ease}.ios-switch.is-on{background:var(--green)}.ios-switch.is-on span{transform:translate(19px)}.action-row{display:flex;flex-wrap:wrap;gap:10px}.balance-adjuster{display:grid;gap:12px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.balance-adjuster-title,.balance-adjuster-actions{display:flex;align-items:center;gap:10px}.balance-adjuster-title{justify-content:space-between}.balance-adjuster-title span,.balance-adjuster-actions span,.balance-adjuster-fields label>span{color:var(--muted);font-size:12px}.balance-adjuster-fields{display:grid;grid-template-columns:110px minmax(0,1fr);gap:10px}.balance-adjuster-fields label{display:grid;gap:6px}.balance-adjuster-fields input{width:100%;min-width:0;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.balance-adjuster-fields input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.balance-adjuster-actions span{min-width:0;overflow-wrap:anywhere}.empty{display:grid;place-items:center;min-height:160px;color:var(--muted);background:var(--group);border:1px dashed var(--hairline-strong);border-radius:18px}.toast{position:fixed;left:50%;bottom:28px;transform:translate(-50%);padding:10px 14px;color:#fff;background:#1d1d1feb;border-radius:999px;font-size:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.secret-dialog-backdrop{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:20px;background:#0000006b;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}.secret-dialog{display:grid;gap:18px;width:min(520px,100%);padding:22px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px;box-shadow:var(--shadow)}.secret-dialog>p{color:var(--muted);line-height:1.55}.secret-dialog code{overflow-x:auto;padding:13px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;white-space:nowrap}.secret-dialog-actions{display:flex;justify-content:flex-end;gap:10px}.auth-page,.account-page{--bg: #f2f2f7;--surface-solid: #ffffff;--group: #f9f9fb;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .16);--blue: #007aff;--green: #34c759;--shadow: 0 18px 45px rgba(0, 0, 0, .08);min-height:100vh;color:var(--text);background:var(--bg)}.auth-page[data-theme=dark],.account-page[data-theme=dark]{--bg: #000000;--surface-solid: #1c1c1e;--group: #2c2c2e;--text: #f5f5f7;--muted: #a1a1aa;--hairline: rgba(255, 255, 255, .12);--shadow: 0 24px 60px rgba(0, 0, 0, .36)}.auth-topbar,.account-topbar{display:flex;align-items:center;justify-content:space-between;width:min(1120px,calc(100% - 40px));min-height:76px;margin:0 auto;border-bottom:1px solid var(--hairline)}.auth-brand{display:inline-flex;align-items:center;gap:10px;padding:0;color:var(--text);background:transparent;cursor:pointer}.auth-brand .brand-mark{width:36px;height:36px;border-radius:10px}.auth-stage{display:grid;grid-template-columns:minmax(0,.9fr) minmax(360px,1fr);align-items:start;width:min(920px,calc(100% - 40px));gap:72px;margin:0 auto;padding:72px 0}.auth-intro{padding-top:24px}.auth-intro>span{color:var(--blue);font-size:13px;font-weight:700}.auth-intro h1{margin:10px 0 14px;font-size:42px}.auth-intro p{max-width:390px;color:var(--muted);line-height:1.65}.auth-form{display:grid;gap:15px;padding:24px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px;box-shadow:var(--shadow)}.auth-form label{display:grid;gap:7px;color:var(--muted);font-size:13px}.auth-form input,.auth-form select{width:100%;height:46px;padding:0 12px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:14px;outline:none}[data-theme=dark] .auth-form input,[data-theme=dark] .auth-form select{color-scheme:dark;background:var(--group)}.auth-form input:focus,.auth-form select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.setup-options{display:grid;gap:12px;padding:14px;border:1px solid var(--hairline);border-radius:18px;background:var(--group)}.setup-options .setting{padding:0;border:0}.setup-options label{gap:7px}.auth-message{min-height:18px;color:#ff3b30;font-size:13px}.auth-submit,.discord-login-button{min-height:44px;width:100%}.auth-submit:disabled{cursor:wait;opacity:.58}.discord-login-button{display:grid;place-items:center;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-weight:700;text-decoration:none}.auth-discord-register{display:grid;gap:10px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.auth-discord-register span{color:var(--muted);font-size:13px;line-height:1.5}.auth-switch{display:flex;justify-content:center}.auth-switch button{padding:6px 10px;color:var(--blue);background:transparent;cursor:pointer}.account-actions,.account-section-title,.account-heading{display:flex;align-items:center;justify-content:space-between;gap:14px}.account-section-title>div{display:grid;gap:3px}.account-content{display:grid;width:min(1120px,calc(100% - 40px));gap:18px;margin:0 auto;padding:42px 0 72px}.account-heading{padding-bottom:18px;border-bottom:1px solid var(--hairline)}.account-balance{text-align:right}.account-balance span,.account-balance strong{display:block}.account-balance span{color:var(--muted);font-size:13px}.account-balance strong{margin-top:4px;font-size:26px}.account-section{display:grid;gap:16px;padding:20px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.check-in-section{overflow:hidden;background:radial-gradient(circle at 100% 0,color-mix(in srgb,var(--blue) 22%,transparent),transparent 48%),var(--glass);border:1px solid var(--glass-border);box-shadow:var(--glass-shadow);-webkit-backdrop-filter:blur(26px) saturate(180%);backdrop-filter:blur(26px) saturate(180%)}.check-in-section .account-section-title>div{display:grid;gap:4px}.check-in-section .eyebrow,.check-in-section h2{margin:0}.check-in-section .primary-button:disabled{cursor:default;opacity:.62}.check-in-summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.check-in-summary>div{display:grid;gap:6px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.check-in-summary span,.check-in-note{color:var(--muted);font-size:13px}.check-in-summary strong{font-size:15px}.check-in-note{margin:0;line-height:1.5}.check-in-message{color:var(--blue)}.one-time-secret{overflow-x:auto;padding:13px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px}.account-message{color:var(--muted);font-size:13px}.account-key-list{display:grid}.account-key-list>div{display:flex;align-items:center;gap:13px;min-height:66px;padding:13px 6px;border-top:1px solid var(--hairline)}.account-key-list>div:first-child{border-top:0}.account-key-list .empty{justify-content:center}.account-key-mark{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:40px;height:40px;color:var(--blue);background:color-mix(in srgb,var(--blue) 13%,transparent);border-radius:12px}.account-key-mark .icon{width:19px;height:19px}.account-key-info{display:flex;flex-direction:column;gap:3px;flex:1 1 auto;min-width:0}.account-key-info strong{font-size:15px;font-weight:650;line-height:1.25}.account-key-info code{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:12.5px;letter-spacing:.01em;color:var(--muted);overflow-wrap:anywhere}.account-key-list .badge{flex:0 0 auto;align-self:center}.account-model-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.account-model-empty{grid-column:1 / -1;padding:26px 18px;color:var(--muted);text-align:center;font-size:13px;background:color-mix(in srgb,var(--group) 60%,transparent);border:1px dashed var(--hairline);border-radius:14px}.account-model-grid article{display:grid;gap:9px;min-width:0;padding:16px;background:var(--group);border:1px solid var(--hairline);border-radius:8px}.account-model-grid article>span,.account-model-grid article p{color:var(--muted);font-size:13px}.account-model-grid article p{line-height:1.5}.account-model-grid code{overflow:hidden;text-overflow:ellipsis}.public-home{--bg: #f4f5f8;--surface: rgba(255, 255, 255, .86);--surface-solid: #ffffff;--group: #eef1f6;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .16);--hairline-strong: rgba(60, 60, 67, .24);--blue: #007aff;--violet: #8b5cf6;--green: #34c759;--orange: #ff9500;--shadow: 0 28px 80px rgba(16, 24, 40, .16);--glow: rgba(0, 122, 255, .15);position:relative;min-height:100vh;padding:22px;color:var(--text);background:var(--bg);overflow:hidden}.public-home:before,.public-home:after{content:"";position:absolute;border-radius:50%;filter:blur(120px);opacity:.5;pointer-events:none;z-index:0}.public-home:before{top:-10%;right:5%;width:600px;height:600px;background:var(--glow)}.public-home:after{bottom:-15%;left:-5%;width:500px;height:500px;background:#8b5cf61f}.public-home>*{position:relative;z-index:1}.public-home[data-theme=dark]{--bg: #050508;--surface: rgba(12, 17, 24, .84);--surface-solid: #0d1117;--group: #0b1017;--text: #f5f5f7;--muted: #8f969f;--hairline: rgba(255, 255, 255, .08);--hairline-strong: rgba(255, 255, 255, .16);--shadow: 0 38px 90px rgba(0, 0, 0, .5);--glow: rgba(0, 122, 255, .25);background:var(--bg)}.public-home[data-theme=dark]:before{opacity:.35}.public-home[data-theme=dark]:after{background:#8b5cf62e;opacity:.4}.home-topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;max-width:1180px;margin:0 auto}.home-brand,.home-actions,.home-cta{display:flex;align-items:center;gap:12px}.home-brand span{display:block;margin-top:2px;color:var(--muted);font-size:13px}.home-hero{display:grid;grid-template-columns:minmax(0,.88fr) minmax(460px,.92fr);gap:clamp(38px,7vw,86px);align-items:center;max-width:1180px;min-height:calc(100vh - 250px);margin:0 auto;padding:clamp(72px,10vw,128px) 0 68px}.home-copy{display:grid;gap:22px;align-content:center}.home-kicker{width:fit-content;padding:8px 13px;color:var(--blue);background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 28%,var(--hairline));border-radius:999px;font-size:13px;font-weight:700}.home-copy h1{max-width:680px;font-size:clamp(42px,4.8vw,58px);line-height:1.08;letter-spacing:0}.home-copy h1 span{display:block;width:fit-content;color:var(--blue);white-space:nowrap}.home-copy p{max-width:620px;color:var(--muted);font-size:17px;font-weight:600;line-height:1.8}.public-home .home-cta .primary-button{gap:8px;min-height:54px;padding:0 28px;color:#fff;background:var(--blue);border-radius:16px;box-shadow:0 4px 14px #007aff59,inset 0 1px #fff3;font-size:15px;font-weight:700}.public-home .home-cta .primary-button:hover{box-shadow:0 6px 20px #007aff73,inset 0 1px #fff3}.public-home[data-theme=dark] .home-cta .primary-button{color:#111318;background:#fff;box-shadow:0 4px 16px #ffffff26,inset 0 1px #ffffff80}.public-home[data-theme=dark] .home-cta .primary-button:hover{box-shadow:0 6px 24px #ffffff38,inset 0 1px #ffffff80}.public-home .home-cta .secondary-button{min-height:54px;padding:0 24px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline-strong);border-radius:16px;box-shadow:0 2px 8px #0000000f;font-size:15px;font-weight:700}.public-home[data-theme=dark] .home-cta .secondary-button{background:#ffffff14;border-color:#ffffff1f;box-shadow:0 2px 10px #0003}.integration-row{display:grid;gap:12px;margin-top:18px;color:var(--muted);font-size:13px;font-weight:700}.integration-row>div{display:flex;flex-wrap:wrap;gap:10px}.integration-row>div span{min-height:40px;padding:11px 18px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:0 2px 6px #0000000a,inset 0 1px #fff9;transition:transform .18s ease,box-shadow .18s ease}.integration-row>div span:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014,inset 0 1px #fff9}.public-home[data-theme=dark] .integration-row>div span{background:#ffffff0f;border-color:#ffffff1a;box-shadow:0 2px 8px #0003,inset 0 1px #ffffff0d}.public-home[data-theme=dark] .integration-row>div span:hover{background:#ffffff1a;box-shadow:0 4px 16px #0000004d,inset 0 1px #ffffff14}.gateway-terminal{position:relative;overflow:hidden;min-height:500px;color:#d7dde7;background:#0a0e14;border:1px solid rgba(255,255,255,.08);border-radius:24px;box-shadow:0 0 0 1px #ffffff0d,0 25px 60px -12px #0006,0 0 40px #007aff14}.gateway-terminal:before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(255,255,255,.03) 0%,transparent 30%);pointer-events:none}.terminal-titlebar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;min-height:54px;padding:0 18px;color:#9aa5b4;background:#111821;border-bottom:1px solid rgba(255,255,255,.08);font-size:13px}.terminal-dots{display:flex;gap:6px}.terminal-dots span{width:9px;height:9px;background:#445061;border-radius:50%}.terminal-status{display:inline-flex;align-items:center;gap:8px;color:#d7dde7}.terminal-status .pulse-dot{width:8px;height:8px}.terminal-endpoint{display:flex;align-items:center;gap:12px;min-height:56px;padding:0 22px;background:#0c1118;border-bottom:1px solid rgba(255,255,255,.08)}.terminal-endpoint span{padding:4px 8px;color:var(--green);background:#34c7591f;border-radius:8px;font-size:11px;font-weight:900}.terminal-endpoint strong{overflow:hidden;color:#f2f5f9;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.terminal-body{display:grid;gap:18px;padding:22px}.terminal-block{display:grid;gap:10px}.terminal-block>span{color:#758194;font-size:12px;font-weight:900;letter-spacing:.14em}.terminal-block pre{overflow-x:auto;margin:0;padding:0;color:#8fd5ff;background:transparent;border:0;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:13px;font-weight:700;line-height:1.75}.terminal-block.response pre{color:#76e4a6}.terminal-route{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.terminal-route div{min-width:0;padding:12px;background:#111821;border:1px solid rgba(255,255,255,.08);border-radius:14px}.terminal-route span{display:block;margin-bottom:6px;color:#758194;font-size:11px;font-weight:800}.terminal-route strong{overflow:hidden;display:block;color:#f2f5f9;font-size:13px;text-overflow:ellipsis;white-space:nowrap}@keyframes status-pulse{0%{box-shadow:0 0 color-mix(in srgb,var(--green) 42%,transparent)}70%{box-shadow:0 0 0 9px color-mix(in srgb,var(--green) 0%,transparent)}to{box-shadow:0 0 color-mix(in srgb,var(--green) 0%,transparent)}}@media(prefers-reduced-motion:reduce){.pulse-dot{animation:none}}.home-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;max-width:1120px;margin:0 auto;padding-bottom:34px}.home-feature{display:grid;gap:9px;min-height:150px;padding:18px;background:var(--surface);border:1px solid var(--hairline);border-radius:24px;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.home-feature .icon{color:var(--blue)}.home-feature span{color:var(--muted);line-height:1.5}@media(max-width:1280px){.users-layout{grid-template-columns:1fr}}@media(max-width:980px){.app-shell{grid-template-columns:1fr}.sidebar{position:fixed;inset:auto 12px 12px;z-index:30;height:auto;padding:8px;border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow)}.ios-window-dots,.brand,.sidebar-footer{display:none}nav{grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.nav-item{flex-direction:column;justify-content:center;gap:4px;min-height:54px;padding:0 4px;border-radius:18px;font-size:11px}.content{width:100%;padding:20px 14px calc(108px + env(safe-area-inset-bottom))}.topbar{margin:-20px -14px 20px;padding:18px 14px 14px}.metrics-grid,.split-grid,.users-layout,.flow-panel,.user-summary-strip,.channel-form-grid{grid-template-columns:1fr}.stream-mode-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.bulk-action-bar{grid-template-columns:auto 100px minmax(160px,1fr)}.channel-form-wide{grid-column:auto}.model-grid{grid-template-columns:1fr}.model-list-toolbar{align-items:stretch;flex-direction:column}.model-list-toolbar input{width:100%}.model-compact-grid{grid-template-columns:1fr}.model-compact-row,.model-compact-row:nth-child(odd),.model-compact-row:nth-last-child(-n+2){border-right:0;border-bottom:1px solid var(--hairline)}.model-compact-row:last-child{border-bottom:0}.flow-steps{grid-template-columns:repeat(4,minmax(136px,1fr));overflow-x:auto;padding-bottom:2px;scroll-snap-type:x mandatory}.flow-step{scroll-snap-align:start}.channels-table,.logs-table{grid-template-columns:minmax(140px,1.3fr) 90px 70px}.logs-toolbar{grid-template-columns:1fr auto}.logs-toolbar .search-box{grid-column:1 / -1}.logs-layout{grid-template-columns:1fr}.log-inspector{position:static}.log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}.channels-table span:nth-child(4),.channels-table span:nth-child(5),.logs-table span:nth-child(3),.logs-table span:nth-child(4),.logs-table span:nth-child(5),.logs-table span:nth-child(6){display:none}}@media(max-width:900px){.home-hero,.home-grid{grid-template-columns:1fr}.home-hero{min-height:0}.model-create-form{grid-template-columns:1fr}.model-create-wide{grid-column:auto}.model-compact-grid{grid-template-columns:1fr}.model-compact-row{grid-template-columns:1fr;align-items:stretch}.model-row-actions{justify-content:flex-start;flex-wrap:wrap}.auth-stage{grid-template-columns:1fr;gap:28px;max-width:560px;padding:38px 0 64px}.auth-intro{padding-top:0}.account-model-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:680px){.app-shell{display:block;min-height:100dvh}.topbar{position:sticky;top:0;align-items:flex-start;flex-direction:column;gap:12px}.topbar-actions{width:100%;display:grid;grid-template-columns:1fr auto auto auto}.segmented-control{flex:1}.segmented-control button{min-width:0}.theme-toggle span{display:none}.theme-toggle{width:40px;padding:0}.topbar-actions .home-link{display:none}.quick-actions{display:flex;overflow-x:auto;padding-bottom:2px;scroll-snap-type:x mandatory}.bulk-action-bar{grid-template-columns:1fr 1fr}.bulk-action-bar strong,.bulk-action-bar input[aria-label=调整原因]{grid-column:1 / -1}.balance-adjuster-fields{grid-template-columns:1fr}.user-filter-row{width:100%;overflow-x:auto}.user-filter-row button{flex:1 0 auto}.auth-default-balance{width:100%}.auth-default-balance input{flex:1;width:auto}.quick-action{min-width:132px;scroll-snap-align:start}.settings-form-grid{grid-template-columns:1fr}.settings-form-wide{grid-column:auto}.settings-save-row{align-items:stretch;flex-direction:column}.settings-save-row .primary-button{width:100%}.auth-topbar,.account-topbar,.auth-stage,.account-content{width:min(100% - 28px,560px)}.auth-intro h1{font-size:34px}.auth-form{padding:18px}.account-model-grid,.check-in-summary{grid-template-columns:1fr}.check-in-section .account-section-title{align-items:stretch;flex-direction:column}.check-in-section .primary-button{width:100%}.check-in-reward-inputs{width:100%;grid-template-columns:repeat(2,minmax(0,1fr))}.account-heading{align-items:flex-start}.public-home{padding:14px}.home-topbar{align-items:flex-start;flex-direction:column}.home-actions{width:100%}.home-actions .primary-button{flex:1}.home-hero{gap:20px;padding:34px 0 20px}.home-copy p{font-size:16px}.home-cta{align-items:stretch;flex-direction:column}.gateway-terminal{min-height:0;border-radius:24px}.terminal-titlebar{grid-template-columns:auto 1fr}.terminal-status{grid-column:1 / -1;justify-content:center;padding:8px 12px;background:#0c1118;border:1px solid rgba(255,255,255,.08);border-radius:999px}.terminal-body,.terminal-endpoint{padding-right:18px;padding-left:18px}.terminal-block pre{font-size:12px}.terminal-route{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:560px){nav{grid-template-columns:repeat(7,minmax(0,1fr))}h1{font-size:30px}.home-copy h1 span{white-space:normal}.metrics-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.setting{align-items:flex-start;flex-direction:column}.registration-mode-control{width:100%}.registration-mode-control button{min-width:0}.hero-strip{align-items:stretch;flex-direction:column;min-height:0;padding:18px}.hero-strip strong{font-size:20px}.live-island{justify-content:center;width:100%}.flow-panel{padding:14px}.flow-steps{display:flex;overflow-x:auto}.flow-step{min-width:136px}.flow-step:not(:last-child):after{display:none}.table{gap:10px;overflow:visible;background:transparent;border:0;border-radius:0}.table-head{display:none}.table-row,.users-table,.channels-table,.logs-table{display:grid;grid-template-columns:1fr auto;gap:8px 12px;min-height:0;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.table-row span:nth-child(n+3){display:none}.users-table.table-row{grid-template-columns:22px minmax(0,1fr) auto}.users-table.table-row>:nth-child(3){display:inline-flex}.mobile-bulk-select{display:inline-flex;width:100%}.channel-editor.channels-table{grid-template-columns:1fr}.channel-editor span:nth-child(n+3),.channel-actions{display:grid}.channel-actions{grid-template-columns:1fr}.table-head,.table-head.users-table,.table-head.channels-table,.table-head.logs-table{display:none}.panel{padding:14px;border-radius:22px}.user-hero{grid-template-columns:48px 1fr}.user-hero .badge{grid-column:1 / -1;justify-self:start}}.modal-backdrop{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;background:#00000073;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal-card{width:100%;max-width:520px;max-height:88vh;overflow-y:auto;padding:22px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:20px;box-shadow:0 20px 60px #00000059}.modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.modal-head strong{font-size:18px}.modal-head>div{display:grid;gap:4px}.modal-head>div>span{color:var(--muted);font-size:13px}.account-add-modal{max-width:680px}.account-add-options{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-top:20px}.account-add-option{position:relative;display:grid;justify-items:start;gap:7px;min-width:0;padding:18px;color:var(--text);text-align:left;cursor:pointer;background:var(--group);border:1px solid var(--hairline);border-radius:16px;transition:border-color .16s ease,background .16s ease,transform .16s ease}.account-add-option:hover:not(:disabled):not(.disabled){transform:translateY(-2px);background:color-mix(in srgb,var(--blue) 7%,var(--group));border-color:color-mix(in srgb,var(--blue) 36%,var(--hairline))}.account-add-option.recommended:after{content:"推荐";position:absolute;top:12px;right:12px;padding:3px 8px;color:var(--blue);font-size:11px;font-weight:700;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border-radius:999px}.account-add-option small{color:var(--muted);line-height:1.45}.account-add-option input{display:none}.account-add-option.disabled{cursor:not-allowed;opacity:.55}.account-add-icon{display:grid;width:34px;height:34px;place-items:center;color:var(--blue);font-size:13px;font-weight:800;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border-radius:11px}.account-add-modal .modal-actions{margin-top:18px}@media(max-width:760px){.channel-card-head{flex-direction:column}.channel-card-head-actions{width:100%;justify-content:flex-start}.account-add-options{grid-template-columns:1fr}}.oauth-steps{margin:16px 0 0;padding-left:18px;display:flex;flex-direction:column;gap:18px}.oauth-steps li{line-height:1.6}.oauth-steps label{display:block;margin-bottom:8px;font-weight:600}.oauth-steps input{width:100%;box-sizing:border-box;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:10px;font-size:14px}.oauth-link{margin-top:10px;display:flex;flex-direction:column;gap:6px}.modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.model-picker-modal{max-width:560px}.model-picker-toolbar{display:flex;align-items:center;gap:8px}.model-picker-search{flex:1 1 auto;min-width:0;height:38px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-picker-search:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-picker-count{margin:10px 2px 8px;color:var(--muted);font-size:12.5px;font-weight:600}.model-picker-list{display:grid;gap:4px;max-height:46vh;overflow-y:auto;padding:4px;border:1px solid var(--hairline);border-radius:14px;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.model-picker-row{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:10px;cursor:pointer}.model-picker-row:hover{background:var(--group)}.model-picker-row.checked{background:color-mix(in srgb,var(--blue) 10%,var(--group))}.model-picker-row input[type=checkbox]{flex:0 0 auto;width:17px;height:17px;accent-color:var(--blue);cursor:pointer}.model-picker-name{flex:1 1 auto;min-width:0;font-size:13.5px;color:var(--text);overflow-wrap:anywhere}.model-picker-tag{flex:0 0 auto;padding:2px 8px;color:var(--blue);background:color-mix(in srgb,var(--blue) 14%,transparent);border-radius:999px;font-size:11px;font-weight:650}.model-picker-status{padding:26px 12px;color:var(--muted);text-align:center;font-size:13px}.model-picker-error{color:#d70015}.form-error{margin-top:14px;padding:10px 12px;color:#d70015;background:color-mix(in srgb,var(--red) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--red) 28%,var(--hairline));border-radius:10px;font-size:13px}.source-guide{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px}.source-guide-item{padding:14px 16px;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.source-guide-item strong{display:block;margin-bottom:4px;font-size:14px}.source-guide-item span{color:var(--muted);font-size:13px;line-height:1.5}.channel-card-collapsible>summary{cursor:pointer;list-style:none}.channel-card-collapsible>summary::-webkit-details-marker{display:none}.channel-card-collapsible>summary:after{content:"展开";align-self:center;margin-left:10px;padding:4px 10px;color:var(--muted);font-size:12px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.channel-card-collapsible[open]>summary:after{content:"收起"}.manual-add{display:inline-block}.manual-add>summary{cursor:pointer;list-style:none}.manual-add>summary::-webkit-details-marker{display:none}.manual-add-body{margin-top:10px;padding:12px;display:flex;flex-direction:column;gap:10px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.manual-add-actions{display:flex;flex-wrap:wrap;gap:8px}.source-tag{flex:0 0 auto;padding:1px 8px;font-size:11px;font-weight:700;border-radius:999px;vertical-align:middle}.source-tag-web{color:#0a7d28;background:color-mix(in srgb,#34c759 16%,var(--surface-solid));border:1px solid color-mix(in srgb,#34c759 32%,var(--hairline))}.source-tag-manual{color:var(--muted);background:var(--group);border:1px solid var(--hairline)}@media(max-width:720px){.source-guide{grid-template-columns:1fr}.account-pool-list{grid-template-columns:minmax(0,1fr)}}.form-success{color:var(--success);font-size:13px}.authsession-field{display:grid;gap:8px;margin-top:18px;color:var(--muted);font-size:13px;font-weight:700}.authsession-field textarea{width:100%;min-height:120px;padding:12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;resize:vertical;outline:none}.authsession-field textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.primary-button,.secondary-button,.danger-button,.icon-button,.theme-toggle{transition:transform .16s ease,background .16s ease,border-color .16s ease,box-shadow .16s ease}.primary-button:hover:not(:disabled){box-shadow:0 8px 20px color-mix(in srgb,var(--blue) 32%,transparent);transform:translateY(-1px)}.secondary-button:hover:not(:disabled),.icon-button:hover:not(:disabled){background:color-mix(in srgb,var(--blue) 9%,var(--surface-solid));border-color:color-mix(in srgb,var(--blue) 18%,var(--hairline))}.channel-page-intro{display:flex;align-items:center;justify-content:space-between;gap:24px;margin:-2px 0 20px;padding:18px 20px;background:linear-gradient(120deg,color-mix(in srgb,var(--blue) 10%,var(--surface-solid)),var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 18%,var(--hairline));border-radius:16px}.channel-page-intro strong,.channel-page-intro span{display:block}.channel-page-intro strong{margin-bottom:5px;font-size:16px}.channel-page-intro>div>span{color:var(--muted);font-size:13px}.channel-page-summary{display:flex;flex:0 0 auto;gap:20px}.channel-page-summary span{color:var(--muted);font-size:12px;white-space:nowrap}.channel-page-summary b{margin-right:4px;color:var(--text);font-size:18px}.channel-toolbar{padding-bottom:14px;border-bottom:1px solid var(--hairline)}.channels-stack{gap:10px}.channel-card-collapsible{gap:0;padding:0;overflow:hidden;border-radius:16px}.channel-card-collapsible[open]{gap:18px;padding:18px}.channel-list-row{display:grid;grid-template-columns:minmax(240px,1.4fr) minmax(130px,.55fr) minmax(150px,.75fr) auto;align-items:center;gap:20px;min-height:86px;padding:14px 18px}.channel-card-collapsible[open] .channel-list-row{min-height:0;padding:0 0 18px;border-bottom:1px solid var(--hairline)}.channel-card-collapsible>.channel-list-row:after{content:none}.channel-identity strong{font-size:15px}.channel-identity span,.channel-identity small{overflow:hidden;max-width:100%;text-overflow:ellipsis;white-space:nowrap}.channel-identity span{margin-top:4px;color:var(--text);font-size:12px;font-weight:650}.channel-identity small{margin-top:4px}.channel-list-meta{display:flex;flex-wrap:wrap;gap:6px 12px;color:var(--muted);font-size:12px}.channel-list-meta b{color:var(--text)}.channel-check-result{display:grid;gap:4px;min-width:0}.channel-check-result>span{margin:0;color:var(--muted);font-size:11px}.channel-check-result b{overflow:hidden;color:var(--muted);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.channel-check-result b.is-ok{color:var(--green)}.channel-check-result b.is-error{color:var(--red)}.channel-list-status{display:flex;align-items:center;justify-content:flex-end;gap:10px}.channel-expand-hint{padding:5px 10px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px}.channel-card-collapsible[open] .channel-expand-hint:after{content:"中"}.channel-editor-controls{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.channel-select-field{display:grid;gap:7px;color:var(--muted);font-size:13px;font-weight:700}.channel-select-field select{width:100%;min-height:40px;padding:0 34px 0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.channel-select-field select:focus{border-color:var(--blue)}.channel-choice-menu{position:relative}.channel-choice-menu>summary{display:flex;align-items:center;justify-content:space-between;min-height:40px;padding:0 12px;color:var(--text);list-style:none;background:var(--group);border:1px solid var(--hairline);border-radius:12px;cursor:pointer}.channel-choice-menu>summary::-webkit-details-marker{display:none}.channel-choice-menu>summary:after{content:"⌄";margin-left:12px;color:var(--muted)}.channel-choice-menu>summary>span{font-weight:650}.channel-choice-menu>summary>small{color:var(--muted);font-size:12px;font-weight:500}.channel-choice-menu>div{position:absolute;top:calc(100% + 7px);right:0;left:0;z-index:20;display:grid;gap:2px;padding:6px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.app-shell[data-theme=dark] .channel-choice-menu>div{background:#2c2c2e;border-color:#ffffff1f}.channel-choice-menu button{display:grid;gap:3px;width:100%;padding:9px 10px;color:var(--text);text-align:left;background:transparent;border:0;border-radius:9px;cursor:pointer}.channel-choice-menu button strong{font-size:13px}.channel-choice-menu button span{color:var(--muted);font-size:12px}.channel-choice-menu button:hover,.channel-choice-menu button.selected{background:color-mix(in srgb,var(--blue) 10%,var(--group))}.channel-choice-menu button.selected strong{color:var(--blue)}.channel-more-actions{position:relative}.channel-more-actions>summary{min-height:36px;padding:0 12px;color:var(--muted);line-height:36px;list-style:none;background:var(--group);border:1px solid var(--hairline);border-radius:10px;cursor:pointer;font-size:13px;font-weight:700}.channel-more-actions>summary::-webkit-details-marker{display:none}.channel-more-actions>summary:after{content:"⌄";margin-left:7px}.channel-more-actions>div{position:absolute;right:0;bottom:calc(100% + 8px);z-index:4;display:grid;width:max-content;gap:6px;padding:8px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:var(--shadow)}.channel-more-actions label{cursor:pointer}.channel-more-actions input{display:none}.channel-card-actions{gap:4px}.channel-card-actions>.secondary-button,.channel-card-actions .channel-more-actions>summary,.channel-model-actions .secondary-button{min-height:34px;padding-inline:10px;color:var(--muted);background:transparent;border-color:transparent;box-shadow:none}.channel-card-actions>.secondary-button:hover:not(:disabled),.channel-card-actions .channel-more-actions>summary:hover,.channel-model-actions .secondary-button:hover:not(:disabled){color:var(--text);background:color-mix(in srgb,var(--blue) 9%,var(--group));border-color:transparent}.channel-card-actions>.primary-button{min-height:36px;padding-inline:15px}.channel-more-actions>summary{line-height:34px}.channel-more-actions>div{padding:6px;border-radius:14px}.channel-more-actions>div .secondary-button,.channel-more-actions>div .danger-button{justify-content:flex-start;min-height:34px;padding-inline:10px;background:transparent;border-color:transparent;border-radius:9px}.channel-more-actions>div .secondary-button:hover:not(:disabled){background:var(--group);border-color:transparent}.channel-more-actions>div .danger-button:hover:not(:disabled){background:color-mix(in srgb,var(--red) 10%,var(--surface-solid));border-color:transparent}@media(max-width:780px){.channel-page-intro{align-items:flex-start;flex-direction:column;gap:14px}.channel-list-row{grid-template-columns:minmax(0,1fr) auto;gap:12px}.channel-list-meta,.channel-check-result{grid-column:1 / -1}.channel-list-meta{order:3}.channel-check-result{order:4}.channel-list-status{grid-column:2;grid-row:1}.channel-editor-controls{grid-template-columns:1fr}}.gateway-terminal .terminal-block{opacity:0;animation:terminal-rise .5s ease-out forwards}.gateway-terminal .terminal-block.response{animation-delay:.45s}.gateway-terminal .terminal-route div{opacity:0;animation:terminal-rise .4s ease-out forwards}.gateway-terminal .terminal-route div:nth-child(1){animation-delay:.18s}.gateway-terminal .terminal-route div:nth-child(2){animation-delay:.28s}.gateway-terminal .terminal-route div:nth-child(3){animation-delay:.38s}.gateway-terminal .terminal-route div:nth-child(4){animation-delay:.48s}.terminal-caret{display:inline-block;width:7px;height:15px;margin-left:2px;vertical-align:text-bottom;background:#76e4a6;border-radius:1px;animation:terminal-caret-blink 1.1s step-end infinite}@keyframes terminal-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes terminal-caret-blink{0%,50%{opacity:1}50.01%,to{opacity:0}}@media(prefers-reduced-motion:reduce){.gateway-terminal .terminal-block,.gateway-terminal .terminal-route div{opacity:1;animation:none}.terminal-caret{animation:none}}.panel,.metric,.hero-strip,.flow-panel,.model-hero,.channel-card,.model-card,.settings-group,.account-pool-row,.model-provider-group,.model-provider-filter button,.table-row,.list-row,.channel-choice-menu button,.provider-picker-menu button,.model-row-menu button{transition:background .16s ease,border-color .16s ease,box-shadow .16s ease}button.table-row:hover,.log-entry .table-row:hover{box-shadow:inset 0 0 0 1px var(--hairline)}.metric:hover{border-color:var(--hairline-strong)}.cli-intro{margin:0 0 16px;color:var(--muted);font-size:14px;line-height:1.6}.cli-credentials{display:grid;gap:8px;margin-bottom:20px}.cli-credential{display:flex;align-items:center;gap:12px;min-height:48px;padding:10px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.cli-credential span{min-width:72px;color:var(--muted);font-size:13px;font-weight:600}.cli-credential code{flex:1;overflow:hidden;padding:0;color:var(--text);background:transparent;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.cli-credential .copy-button{display:grid;place-items:center;flex-shrink:0;width:32px;height:32px;color:var(--muted);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;cursor:pointer;transition:color .14s ease,border-color .14s ease}.cli-credential .copy-button:hover{color:var(--text);border-color:var(--hairline-strong)}.cli-credential .copy-button .icon{width:15px;height:15px}.cli-tools{display:grid;gap:10px}.cli-tool{overflow:hidden;background:var(--group);border:1px solid var(--hairline);border-radius:14px;transition:border-color .16s ease}.cli-tool[open]{border-color:var(--hairline-strong)}.cli-tool summary{display:flex;align-items:center;gap:12px;min-height:52px;padding:12px 16px;cursor:pointer;list-style:none}.cli-tool summary::-webkit-details-marker{display:none}.cli-tool summary:before{content:"";display:block;width:6px;height:6px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(-45deg);transition:transform .16s ease}.cli-tool[open] summary:before{transform:rotate(45deg)}.cli-tool summary strong{flex:1;color:var(--text);font-size:14px;font-weight:700}.cli-tool summary span{color:var(--muted);font-size:12px}.cli-tool>p,.cli-tool>pre{margin:0 16px 14px}.cli-tool>p{color:var(--muted);font-size:13px;line-height:1.55}.cli-tool>p code{padding:2px 6px;color:var(--text);background:var(--surface-solid);border-radius:5px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px}.cli-tool>pre{overflow-x:auto;padding:14px 16px;color:#8fd5ff;background:#0d1117;border-radius:10px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;font-weight:600;line-height:1.7;white-space:pre-wrap;word-break:break-all}.app-shell[data-theme=dark] .cli-tool>pre{background:#0006}.cli-tool>pre+pre{margin-top:-4px}.cli-message{margin:16px 0 0;padding:10px 14px;color:var(--green);background:color-mix(in srgb,var(--green) 8%,transparent);border-radius:10px;font-size:13px;font-weight:600}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes slide-up{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes scale-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes pop{0%{transform:scale(1)}50%{transform:scale(.95)}to{transform:scale(1)}}@keyframes toast-in{0%{opacity:0;transform:translateY(16px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.content{animation:fade-in .25s ease-out}.panel,.settings-group,.flow-panel,.hero-strip{animation:slide-up .3s ease-out backwards}.panel:nth-child(1),.settings-group:nth-child(1){animation-delay:0ms}.panel:nth-child(2),.settings-group:nth-child(2){animation-delay:50ms}.panel:nth-child(3),.settings-group:nth-child(3){animation-delay:.1s}.panel:nth-child(4),.settings-group:nth-child(4){animation-delay:.15s}.metric,.channel-card,.model-card,.cli-tool,.cli-credential{animation:slide-up .28s ease-out backwards}.metric:nth-child(1),.channel-card:nth-child(1),.model-card:nth-child(1){animation-delay:0ms}.metric:nth-child(2),.channel-card:nth-child(2),.model-card:nth-child(2){animation-delay:40ms}.metric:nth-child(3),.channel-card:nth-child(3),.model-card:nth-child(3){animation-delay:80ms}.metric:nth-child(4),.channel-card:nth-child(4),.model-card:nth-child(4){animation-delay:.12s}.metric:nth-child(5),.channel-card:nth-child(5),.model-card:nth-child(5){animation-delay:.16s}.metric:nth-child(6),.channel-card:nth-child(6),.model-card:nth-child(6){animation-delay:.2s}.table-row,.list-row{animation:fade-in .2s ease-out backwards}.primary-button,.secondary-button,.danger-button{transition:transform .12s ease,box-shadow .12s ease,background .14s ease,border-color .14s ease}.primary-button:hover,.secondary-button:hover,.danger-button:hover{transform:translateY(-1px)}.primary-button:active,.secondary-button:active,.danger-button:active{transform:translateY(0) scale(.98)}.ios-switch{transition:background .18s ease}.ios-switch span{transition:transform .2s cubic-bezier(.34,1.56,.64,1)}.metric:hover,.channel-card:hover,.model-card:hover{transform:translateY(-2px);box-shadow:0 6px 20px #00000014}.app-shell[data-theme=dark] .metric:hover,.app-shell[data-theme=dark] .channel-card:hover,.app-shell[data-theme=dark] .model-card:hover{box-shadow:0 6px 24px #00000047}.metric,.channel-card,.model-card{transition:transform .18s ease,box-shadow .18s ease,border-color .16s ease}.nav-item{transition:background .14s ease,color .14s ease,transform .1s ease}.nav-item:hover{transform:translate(2px)}.nav-item:active{transform:translate(0) scale(.98)}.settings-tabs button{transition:transform .12s ease,color .14s ease,background .14s ease,box-shadow .14s ease}.settings-tabs button:active{transform:scale(.97)}.toast{animation:toast-in .28s cubic-bezier(.34,1.25,.64,1)}.secret-dialog-backdrop{animation:fade-in .2s ease-out}.secret-dialog{animation:scale-in .25s cubic-bezier(.34,1.25,.64,1)}.copy-button,.cli-credential .copy-button{transition:transform .1s ease,color .14s ease,border-color .14s ease,background .14s ease}.copy-button:active,.cli-credential .copy-button:active{transform:scale(.9)}.channel-choice-menu>div,.provider-picker-menu>div,.model-row-menu{animation:slide-down .18s ease-out}@keyframes pulse-subtle{0%,to{opacity:1}50%{opacity:.7}}.pulse-dot{animation:pulse-subtle 2s ease-in-out infinite}.cli-tool summary{transition:background .14s ease}.cli-tool summary:hover{background:color-mix(in srgb,var(--surface-solid) 50%,transparent)}.cli-tool summary:before{transition:transform .2s cubic-bezier(.34,1.25,.64,1)}.icon{transition:transform .14s ease}button:hover .icon{transform:scale(1.08)}button:active .icon{transform:scale(.95)}.segmented-control button{transition:color .14s ease,background .14s ease,box-shadow .14s ease,transform .1s ease}.segmented-control button:active{transform:scale(.96)}.theme-toggle{transition:transform .12s ease,background .14s ease,border-color .14s ease}.theme-toggle:hover{transform:scale(1.03)}.theme-toggle:active{transform:scale(.97)}input,select,textarea{transition:border-color .14s ease,box-shadow .14s ease}.auth-form{animation:scale-in .3s cubic-bezier(.34,1.15,.64,1)}.account-section{animation:slide-up .3s ease-out backwards}.account-section:nth-child(1){animation-delay:0ms}.account-section:nth-child(2){animation-delay:80ms}.account-section:nth-child(3){animation-delay:.16s}.home-hero{animation:fade-in .4s ease-out}.home-copy{animation:slide-up .4s ease-out .1s backwards}.brand{transition:transform .14s ease}.brand:hover{transform:scale(1.02)}.quick-action{transition:transform .14s ease,background .14s ease,border-color .14s ease,box-shadow .14s ease}.quick-action:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.quick-action:active{transform:translateY(0) scale(.98)}.table-row{transition:background .12s ease,box-shadow .12s ease,transform .1s ease}button.table-row:active{transform:scale(.995)}.badge:before{transition:transform .2s ease,opacity .2s ease}.badge:hover:before{transform:scale(1.3)}.model-list-toolbar input,.user-filter-row input,.search-input{transition:border-color .16s ease,box-shadow .16s ease,background .16s ease}.model-list-toolbar input:focus,.user-filter-row input:focus,.search-input:focus{background:var(--surface-solid)}.pager button{transition:transform .1s ease,background .12s ease,border-color .12s ease}.pager button:hover:not(:disabled){transform:scale(1.05)}.pager button:active:not(:disabled){transform:scale(.95)}details summary{transition:background .14s ease,color .14s ease}details[open]>summary{color:var(--text)}.list-row{transition:background .12s ease,transform .1s ease}.list-row:hover{background:color-mix(in srgb,var(--group) 50%,transparent)}.channel-card,.model-card{animation:slide-up .25s ease-out backwards}.channel-card:nth-child(1),.model-card:nth-child(1){animation-delay:0ms}.channel-card:nth-child(2),.model-card:nth-child(2){animation-delay:30ms}.channel-card:nth-child(3),.model-card:nth-child(3){animation-delay:60ms}.channel-card:nth-child(4),.model-card:nth-child(4){animation-delay:90ms}.channel-card:nth-child(5),.model-card:nth-child(5){animation-delay:.12s}.channel-card:nth-child(6),.model-card:nth-child(6){animation-delay:.15s}.channel-card:nth-child(7),.model-card:nth-child(7){animation-delay:.18s}.channel-card:nth-child(8),.model-card:nth-child(8){animation-delay:.21s}.users-layout .table-row.selected{animation:pop .2s ease-out}.user-filter-row button,.model-filter-actions button,.log-status-filter button,.model-provider-filter button{transition:transform .1s ease,color .12s ease,background .12s ease,box-shadow .12s ease}.user-filter-row button:active,.model-filter-actions button:active,.log-status-filter button:active,.model-provider-filter button:active{transform:scale(.96)}.bulk-action-bar{animation:slide-up .2s ease-out}.secret-dialog code{animation:fade-in .3s ease-out .15s backwards}.gateway-terminal{animation:scale-in .5s cubic-bezier(.16,1,.3,1) .2s backwards}.home-kicker{animation:slide-up .35s ease-out backwards}.home-cta{animation:slide-up .4s ease-out .15s backwards}.integration-row>div span{animation:slide-up .3s ease-out backwards}.integration-row>div span:nth-child(1){animation-delay:.25s}.integration-row>div span:nth-child(2){animation-delay:.3s}.integration-row>div span:nth-child(3){animation-delay:.35s}.topbar{animation:slide-down .3s ease-out}.nav-item{animation:fade-in .25s ease-out backwards}nav .nav-item:nth-child(1){animation-delay:0ms}nav .nav-item:nth-child(2){animation-delay:30ms}nav .nav-item:nth-child(3){animation-delay:60ms}nav .nav-item:nth-child(4){animation-delay:90ms}nav .nav-item:nth-child(5){animation-delay:.12s}nav .nav-item:nth-child(6){animation-delay:.15s}nav .nav-item:nth-child(7){animation-delay:.18s}nav .nav-item:nth-child(8){animation-delay:.21s}.sidebar-footer{animation:fade-in .4s ease-out .2s backwards}input:focus,select:focus,textarea:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 15%,transparent)}.provider-icon{transition:transform .15s ease}.channel-card:hover .provider-icon,.model-card:hover .provider-icon{transform:scale(1.1)}input[type=checkbox],input[type=radio]{transition:transform .1s ease,box-shadow .1s ease}input[type=checkbox]:active,input[type=radio]:active{transform:scale(.9)}.log-inspector{animation:slide-up .25s ease-out}.model-hero{animation:slide-up .35s ease-out backwards}.flow-step{animation:slide-up .3s ease-out backwards}.flow-step:nth-child(1){animation-delay:0ms}.flow-step:nth-child(2){animation-delay:60ms}.flow-step:nth-child(3){animation-delay:.12s}.flow-step:nth-child(4){animation-delay:.18s}.hero-strip{animation:fade-in .35s ease-out backwards}.empty{animation:fade-in .3s ease-out}.account-model-grid article{animation:slide-up .25s ease-out backwards;transition:transform .15s ease,box-shadow .15s ease}.account-model-grid article:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.account-model-grid article:nth-child(1){animation-delay:0ms}.account-model-grid article:nth-child(2){animation-delay:25ms}.account-model-grid article:nth-child(3){animation-delay:50ms}.account-model-grid article:nth-child(4){animation-delay:75ms}.account-model-grid article:nth-child(5){animation-delay:.1s}.account-model-grid article:nth-child(6){animation-delay:125ms}.account-key-list>div{animation:slide-up .25s ease-out backwards}.account-key-list>div:nth-child(1){animation-delay:0ms}.account-key-list>div:nth-child(2){animation-delay:40ms}.account-key-list>div:nth-child(3){animation-delay:80ms}.one-time-secret{animation:scale-in .3s cubic-bezier(.34,1.25,.64,1)}.account-balance{animation:fade-in .4s ease-out .1s backwards}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}.pulse-dot{animation:none}}.app-shell{--glass: linear-gradient(158deg, rgba(255, 255, 255, .92) 0%, rgba(255, 255, 255, .64) 100%);--glass-border: rgba(255, 255, 255, .72);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), 0 1px 2px rgba(17, 24, 39, .04), 0 12px 34px rgba(17, 24, 39, .08);background:radial-gradient(1120px 620px at 6% -8%,rgba(0,122,255,.1),transparent 58%),radial-gradient(960px 560px at 102% 2%,rgba(48,176,199,.1),transparent 56%),radial-gradient(900px 760px at 50% 118%,rgba(255,149,0,.06),transparent 60%),var(--bg)}.app-shell[data-theme=dark]{--glass: linear-gradient(158deg, rgba(58, 58, 66, .72) 0%, rgba(28, 28, 34, .6) 100%);--glass-border: rgba(255, 255, 255, .1);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .3), 0 18px 44px rgba(0, 0, 0, .48);background:radial-gradient(1120px 620px at 6% -8%,rgba(10,132,255,.18),transparent 58%),radial-gradient(960px 560px at 102% 2%,rgba(48,176,199,.15),transparent 56%),radial-gradient(900px 760px at 50% 120%,rgba(120,88,255,.14),transparent 60%),var(--bg)}.account-page,.auth-page{--glass: linear-gradient(158deg, rgba(255, 255, 255, .94) 0%, rgba(255, 255, 255, .66) 100%);--glass-border: rgba(255, 255, 255, .75);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 1px 2px rgba(17, 24, 39, .04), 0 16px 40px rgba(17, 24, 39, .09);background:radial-gradient(1080px 640px at 4% -10%,rgba(0,122,255,.12),transparent 56%),radial-gradient(940px 560px at 104% 4%,rgba(48,176,199,.1),transparent 54%),radial-gradient(880px 720px at 52% 120%,rgba(175,82,222,.07),transparent 60%),var(--bg)}.account-page[data-theme=dark],.auth-page[data-theme=dark]{--glass: linear-gradient(158deg, rgba(58, 58, 66, .7) 0%, rgba(24, 24, 30, .58) 100%);--glass-border: rgba(255, 255, 255, .12);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .35), 0 22px 52px rgba(0, 0, 0, .5);background:radial-gradient(1080px 640px at 4% -10%,rgba(10,132,255,.22),transparent 56%),radial-gradient(940px 560px at 104% 4%,rgba(48,176,199,.16),transparent 54%),radial-gradient(880px 720px at 52% 122%,rgba(175,82,222,.16),transparent 60%),var(--bg)}.metric,.panel,.account-section:not(.check-in-section),.settings-group,.model-card,.channel-card,.flow-panel,.hero-strip,.model-hero,.log-inspector,.source-guide-item{background:var(--glass);border:1px solid var(--glass-border);box-shadow:var(--glass-shadow);-webkit-backdrop-filter:blur(26px) saturate(185%);backdrop-filter:blur(26px) saturate(185%)}.app-shell[data-theme=dark] .metric,.app-shell[data-theme=dark] .panel,.app-shell[data-theme=dark] .settings-group,.app-shell[data-theme=dark] .model-card,.app-shell[data-theme=dark] .channel-card,.app-shell[data-theme=dark] .flow-panel,.app-shell[data-theme=dark] .hero-strip,.app-shell[data-theme=dark] .model-hero,.app-shell[data-theme=dark] .log-inspector,.app-shell[data-theme=dark] .source-guide-item{background:var(--glass);border-color:var(--glass-border);box-shadow:var(--glass-shadow)}.group-assign-row{display:grid;gap:6px;margin-top:4px;padding:12px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.group-assign-row label{display:grid;gap:6px;color:var(--muted);font-size:12px}.group-assign-row select{height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.group-assign-row select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.group-assign-row small{color:var(--muted);font-size:12px;line-height:1.5}.channel-group-field{display:grid;gap:8px;padding:12px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.channel-group-empty{color:var(--muted);font-size:13px;line-height:1.5}.channel-group-options{display:flex;flex-wrap:wrap;gap:8px}.channel-group-options button{display:grid;gap:2px;min-width:0;padding:8px 12px;color:var(--text);text-align:left;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;cursor:pointer}.channel-group-options button small{color:var(--muted)}.channel-group-options button.selected{border-color:color-mix(in srgb,var(--blue) 46%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 28%,transparent)}.app-shell[data-theme=dark] .group-assign-row select,.app-shell[data-theme=dark] .channel-group-options button,.app-shell[data-theme=dark] .group-edit-fields input{background:#7676801f;border-color:transparent}.group-edit-fields{display:grid;gap:8px}.group-edit-fields input{height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.group-edit-fields input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)} +:root{color:#1d1d1f;background:#f2f2f7;font-family:-apple-system,BlinkMacSystemFont,SF Pro Display,Segoe UI,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}*{box-sizing:border-box}body{margin:0;min-width:320px;min-height:100vh}button,input,select,textarea{font:inherit}button{border:0}.app-shell select:not([multiple]){appearance:none;padding-right:38px!important;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%)!important;background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%!important;background-size:5px 5px,5px 5px!important;background-repeat:no-repeat!important;cursor:pointer}.app-shell[data-theme=dark] select{color-scheme:dark}.app-shell[data-theme=dark] select option{color:#f5f5f7;background:#2c2c2e}.app-shell input[type=datetime-local],.app-shell input[type=date],.app-shell input[type=time]{color-scheme:dark}.app-shell input[type=datetime-local]::-webkit-calendar-picker-indicator,.app-shell input[type=date]::-webkit-calendar-picker-indicator,.app-shell input[type=time]::-webkit-calendar-picker-indicator{opacity:.72;cursor:pointer}.app-shell input[type=number]{appearance:textfield}.app-shell input[type=number]::-webkit-inner-spin-button,.app-shell input[type=number]::-webkit-outer-spin-button{margin:0;appearance:none}.app-shell{--bg: #f2f2f7;--surface: rgba(255, 255, 255, .78);--surface-solid: #ffffff;--group: #f4f5f7;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .12);--hairline-strong: rgba(60, 60, 67, .2);--blue: #007aff;--green: #34c759;--red: #ff3b30;--orange: #ff9500;--teal: #30b0c7;--shadow: 0 2px 8px rgba(0, 0, 0, .04), 0 12px 32px rgba(0, 0, 0, .06);--shadow-lg: 0 4px 12px rgba(0, 0, 0, .05), 0 20px 48px rgba(0, 0, 0, .1);--row-height: 58px;display:grid;grid-template-columns:264px 1fr;min-height:100vh;color:var(--text);background:var(--bg)}.app-shell[data-theme=dark]{--bg: #0a0a0c;--surface: rgba(22, 22, 26, .8);--surface-solid: #161618;--group: rgba(255, 255, 255, .04);--text: #f5f5f7;--muted: #8e8e93;--hairline: rgba(255, 255, 255, .06);--hairline-strong: rgba(255, 255, 255, .1);--shadow: 0 2px 8px rgba(0, 0, 0, .2), 0 12px 32px rgba(0, 0, 0, .25);--shadow-lg: 0 4px 12px rgba(0, 0, 0, .3), 0 24px 56px rgba(0, 0, 0, .4);background:var(--bg);color-scheme:dark}.app-shell[data-density=compact]{--row-height: 48px}.sidebar{position:sticky;top:0;height:100vh;padding:16px 14px;background:var(--surface-solid);border-right:1px solid var(--hairline);box-shadow:2px 0 12px #00000008}.app-shell[data-theme=dark] .sidebar{background:#111113;border-right-color:#ffffff0d;box-shadow:2px 0 16px #00000040}.ios-window-dots{display:flex;gap:7px;padding:4px 10px 18px;cursor:default}.ios-window-dots span{width:12px;height:12px;border-radius:50%;opacity:.85;transition:opacity .16s ease,transform .16s ease}.ios-window-dots:hover span{opacity:1}.ios-window-dots span:hover{transform:scale(1.18)}.ios-window-dots span:nth-child(1){background:#ff5f57}.ios-window-dots span:nth-child(2){background:#ffbd2e}.ios-window-dots span:nth-child(3){background:#28c840}.brand{display:flex;align-items:center;gap:12px;padding:0 10px 24px}.brand-mark{display:grid;place-items:center;width:42px;height:42px;color:#fff;background:#1d1d1f;border-radius:13px;font-weight:800;box-shadow:inset 0 1px #ffffff2e}.app-shell[data-theme=dark] .brand-mark{color:#fff;background:#76768033;border:0}.brand strong,.brand span{display:block}.brand span{margin-top:2px;color:var(--muted);font-size:13px}nav{display:grid;gap:6px}.nav-item{position:relative;display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:0 12px;color:var(--muted);background:transparent;border-radius:12px;cursor:pointer;text-align:left}.nav-item:hover{color:var(--text);background:var(--group)}.nav-item.active{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000000f,inset 0 0 0 1px var(--hairline)}.app-shell[data-theme=dark] .nav-item:hover{background:#ffffff0d}.app-shell[data-theme=dark] .nav-item.active{color:#fff;background:#ffffff14;box-shadow:0 1px 6px #0003,inset 0 0 0 1px #ffffff0f}.sidebar-footer{position:absolute;left:14px;right:14px;bottom:16px;display:flex;justify-content:space-between;align-items:center;min-height:44px;padding:0 12px;color:var(--muted);background:var(--group);border-radius:14px;font-size:13px}.sidebar-footer strong{display:inline-flex;align-items:center;gap:7px;color:var(--green)}.sidebar-footer .pulse-dot{width:7px;height:7px}.icon{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:0 0 auto}.content{width:calc(100vw - 264px);padding:28px 30px 44px;background:var(--bg)}.topbar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;gap:18px;margin:-28px -30px 24px;padding:24px 30px 18px;background:color-mix(in srgb,var(--bg) 82%,transparent);border-bottom:1px solid var(--hairline);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.app-shell[data-theme=dark] .topbar{background:#000000d1;border-bottom-color:#ffffff14}.topbar-actions,.panel-toolbar,.setting-value{display:flex;align-items:center;gap:10px}.eyebrow{margin:0 0 5px;color:var(--muted);font-size:13px}h1,h2,h3,p{margin:0}h1{font-size:34px;line-height:1.08;letter-spacing:0}h2{font-size:18px;letter-spacing:0}h3{margin:6px 0 10px;font-size:14px;color:var(--muted)}.primary-button,.secondary-button,.danger-button,.icon-button,.theme-toggle{display:inline-flex;align-items:center;justify-content:center;min-height:38px;border-radius:999px;cursor:pointer;text-decoration:none}.primary-button{padding:0 18px;color:#fff;background:var(--blue);font-weight:700;box-shadow:0 2px 6px #007aff40;box-shadow:0 5px 14px color-mix(in srgb,var(--blue) 24%,transparent)}.secondary-button{padding:0 16px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline-strong);font-weight:650;box-shadow:0 1px 3px #0000000a}.danger-button{padding:0 16px;color:#d70015;background:color-mix(in srgb,var(--red) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--red) 28%,var(--hairline));font-weight:700}.compact-button{min-height:32px;padding:0 12px;font-size:13px}.icon-button{width:38px;color:var(--text);background:var(--group);border:1px solid var(--hairline)}.theme-toggle{gap:8px;padding:0 14px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline)}.app-shell[data-theme=dark] .secondary-button,.app-shell[data-theme=dark] .icon-button,.app-shell[data-theme=dark] .theme-toggle,.app-shell[data-theme=dark] .compact-button{background:#ffffff14;border-color:#ffffff1a;box-shadow:0 1px 4px #00000026}.primary-button:disabled,.secondary-button:disabled,.danger-button:disabled,.icon-button:disabled,.theme-toggle:disabled{cursor:not-allowed;opacity:.55}.muted-inline{color:var(--muted);font-size:13px}.status-button{display:inline-flex;justify-content:flex-start;padding:0;background:transparent;border:0;cursor:pointer}.segmented-control{display:inline-grid;grid-auto-flow:column;gap:2px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.app-shell[data-theme=dark] .segmented-control,.app-shell[data-theme=dark] .user-filter-row,.app-shell[data-theme=dark] .model-filter-actions,.app-shell[data-theme=dark] .log-status-filter,.app-shell[data-theme=dark] .settings-tabs,.app-shell[data-theme=dark] .registration-mode-control{background:#7676801f;border-color:transparent}.segmented-control button{min-width:54px;height:30px;padding:0 12px;color:var(--muted);background:transparent;border-radius:999px;cursor:pointer}.segmented-control button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.app-shell[data-theme=dark] .segmented-control button.selected,.app-shell[data-theme=dark] .user-filter-row button.selected,.app-shell[data-theme=dark] .model-filter-actions button.selected,.app-shell[data-theme=dark] .log-status-filter button.selected,.app-shell[data-theme=dark] .settings-tabs button.selected,.app-shell[data-theme=dark] .registration-mode-control button.selected{background:#ffffff1f;box-shadow:none}.page-stack{display:grid;gap:18px}.hero-strip{display:flex;align-items:center;justify-content:space-between;gap:18px;min-height:128px;padding:24px;background:var(--surface);border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.hero-strip span,.metric span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.hero-strip strong{display:block;font-size:22px;letter-spacing:0}.hero-strip p{max-width:620px;margin-top:8px;color:var(--muted);line-height:1.55}.live-island{display:inline-flex;align-items:center;gap:8px;min-width:92px;height:34px;padding:0 14px;color:#fff;background:#1d1d1f;border:1px solid var(--hairline);border-radius:999px;font-weight:700;box-shadow:inset 0 1px #ffffff29}.app-shell[data-theme=dark] .live-island{color:var(--muted);background:var(--group)}.hero-strip .live-island{margin-right:4px}.pulse-dot{width:9px;height:9px;background:var(--green);border-radius:50%;box-shadow:0 0 0 5px color-mix(in srgb,var(--green) 20%,transparent);animation:status-pulse 1.8s ease-out infinite}.quick-actions{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.quick-action{display:flex;align-items:center;justify-content:center;gap:9px;min-height:48px;padding:0 14px;color:var(--text);background:var(--surface);border:1px solid var(--hairline);border-radius:999px;cursor:pointer;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.quick-action:nth-child(1){color:var(--blue)}.quick-action:nth-child(2){color:var(--teal)}.quick-action:nth-child(3){color:var(--green)}.quick-action:nth-child(4){color:var(--orange)}.metrics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}.metric,.panel{background:var(--surface-solid);border:1px solid var(--hairline);box-shadow:var(--shadow)}.app-shell[data-theme=dark] .quick-action,.app-shell[data-theme=dark] .metric,.app-shell[data-theme=dark] .panel,.app-shell[data-theme=dark] .hero-strip,.app-shell[data-theme=dark] .flow-panel,.app-shell[data-theme=dark] .model-hero{background:var(--surface-solid);border-color:var(--hairline);box-shadow:var(--shadow)}.metric{min-height:118px;padding:18px;border-radius:22px}.metric strong{display:block;overflow:hidden;font-size:31px;letter-spacing:0;text-overflow:ellipsis;white-space:nowrap}.split-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.flow-panel{display:grid;grid-template-columns:minmax(190px,.7fr) minmax(0,1.3fr);gap:18px;align-items:center;padding:18px;background:var(--surface);border:1px solid var(--hairline);border-radius:24px;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.flow-copy span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.flow-copy strong{display:block;font-size:20px;line-height:1.3}.flow-steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.flow-step{position:relative;min-height:104px;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.flow-step:not(:last-child):after{content:"";position:absolute;top:50%;right:-10px;width:10px;height:1px;background:var(--hairline-strong)}.flow-index{display:grid;place-items:center;width:28px;height:28px;margin-bottom:12px;color:#fff;background:var(--blue);border-radius:50%;font-size:13px;font-weight:800}.flow-step strong,.flow-step span{display:block}.flow-step span{margin-top:4px;color:var(--muted);font-size:13px}.panel{padding:20px;border-radius:20px;min-width:0}.app-shell[data-theme=dark] .panel{border-radius:18px}.panel-title{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding:0 2px}.panel-title h2{font-size:17px;font-weight:700}.app-shell[data-theme=dark] .panel-title{padding-bottom:14px;border-bottom:1px solid rgba(255,255,255,.06)}.list-row,.setting{display:flex;align-items:center;justify-content:space-between;gap:14px;min-height:var(--row-height);padding:10px 2px;border-top:1px solid var(--hairline)}.list-row:first-of-type,.setting:first-child{border-top:0}.list-row>div,.setting>div{min-width:0}.row-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:8px;flex-shrink:0}.list-row strong,.list-row span,.setting span,.setting strong,.table-row span,.table-row strong,.table-row small{min-width:0}.list-row strong,.list-row span{display:block}.list-row span,.table-row small{margin-top:3px;color:var(--muted);font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.overview-channel-row>div{flex:1 1 auto;overflow:hidden}.overview-channel-row>.badge{flex:0 0 auto;min-width:54px;overflow:visible}.badge{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:54px;height:27px;padding:0 11px;color:var(--muted);background:var(--group);border-radius:999px;font-size:12px;font-weight:650;letter-spacing:.01em;white-space:nowrap}.app-shell[data-theme=dark] .badge{background:#76768024;border:0}.badge.tone-active:before,.badge.tone-healthy:before,.badge.tone-available:before,.badge.tone-success:before,.badge.tone-disabled:before,.badge.tone-failed:before,.badge.tone-limited:before,.badge.tone-overdue:before,.badge.tone-standby:before{content:"";display:inline-block;width:5px;height:5px;border-radius:50%;background:currentColor;flex:0 0 auto}.tone-active,.tone-healthy,.tone-available,.tone-success{color:#118446;background:color-mix(in srgb,var(--green) 16%,transparent)}.tone-disabled,.tone-failed{color:#d70015;background:color-mix(in srgb,var(--red) 14%,transparent)}.tone-limited,.tone-overdue,.tone-standby{color:#a05a00;background:color-mix(in srgb,var(--orange) 15%,transparent)}.users-layout{display:grid;grid-template-columns:minmax(780px,1.55fr) minmax(380px,.7fr);gap:18px;align-items:start}.users-layout .panel:first-child{padding:14px}.users-layout .panel:first-child .table{background:transparent;border:0;border-radius:0;gap:8px}.users-layout .panel:first-child .table-head{min-height:34px;padding:0 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-head{background:#7676801a;border-color:transparent}.users-layout .panel:first-child .table-row{min-height:56px;padding:0 14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:16px}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row{background:#1c1c1ec7;border-color:#ffffff0d}.users-layout .panel:first-child .table-row:hover{background:var(--group)}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row:hover{background:#2c2c2ee0}.users-layout .panel:first-child .table-row.selected{border-color:color-mix(in srgb,var(--blue) 45%,var(--hairline));box-shadow:inset 3px 0 0 var(--blue)}.app-shell[data-theme=dark] .users-layout .panel:first-child .table-row.selected{background:#76768029;border-color:transparent;box-shadow:none}.user-summary-strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:12px}.user-summary-strip span{min-height:50px;padding:10px 12px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:14px;font-size:13px}.user-summary-strip strong{display:block;color:var(--text);font-size:20px}.user-filter-row{display:flex;gap:4px;width:fit-content;margin-bottom:12px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.user-filter-row button{min-height:30px;padding:0 13px;color:var(--muted);background:transparent;border-radius:999px;cursor:pointer;font-weight:700}.user-filter-row button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.mobile-bulk-select{display:none;margin-bottom:12px}.bulk-action-bar{display:grid;grid-template-columns:auto 100px minmax(160px,1fr) auto auto auto minmax(130px,auto) auto;align-items:center;gap:8px;margin-bottom:12px;padding:10px;background:color-mix(in srgb,var(--blue) 8%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 25%,var(--hairline));border-radius:12px}.bulk-group-select{min-width:0;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.bulk-group-select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.app-shell[data-theme=dark] .bulk-group-select{background:#7676801f;border-color:transparent}.auth-default-balance select{min-width:0;width:180px;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.auth-default-balance select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.app-shell[data-theme=dark] .auth-default-balance select{background:#7676801f;border-color:transparent}.bulk-action-bar input,.auth-default-balance input{min-width:0;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.bulk-action-bar input:focus,.auth-default-balance input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.pagination-bar{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:12px;color:var(--muted);font-weight:700}.models-page{display:grid;gap:18px;width:100%}.model-hero{padding:18px 22px;background:var(--surface);border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.model-hero span{display:block;margin-bottom:8px;color:var(--muted);font-size:13px}.model-hero strong{display:block;font-size:24px;line-height:1.3}.model-hero p{margin-top:8px;color:var(--muted)}.model-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.model-list{display:grid;gap:10px}.model-list-toolbar{justify-content:space-between;align-items:center}.model-list-toolbar input{flex:1 1 460px;width:auto;max-width:720px;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-list-toolbar input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-filter-actions{display:inline-flex;gap:6px;padding:4px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.model-filter-actions button{height:32px;padding:0 12px;color:var(--muted);background:transparent;border:0;border-radius:999px}.model-filter-actions button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.model-provider-filter{display:flex;gap:8px;margin:14px 0;padding-bottom:2px;overflow-x:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 45%,transparent) transparent}.model-provider-filter button{display:grid;grid-template-columns:34px minmax(0,1fr) auto;align-items:center;gap:10px;flex:0 0 240px;min-height:58px;padding:10px;color:var(--text);text-align:left;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.model-provider-filter button.selected{background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 46%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 28%,transparent)}.app-shell[data-theme=dark] .model-provider-filter button.selected,.app-shell[data-theme=dark] .provider-chip-grid button.selected,.app-shell[data-theme=dark] .stream-mode-grid button.selected{background:#ffffff1f;border-color:transparent;box-shadow:none}.model-provider-filter strong,.model-provider-filter small{display:block;min-width:0}.model-provider-filter strong{overflow-wrap:anywhere}.model-provider-filter small{color:var(--muted);font-weight:800}.provider-icon-all{display:grid;place-items:center;flex:0 0 38px;width:38px;height:38px;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.02em;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 26%,var(--hairline));border-radius:10px}.model-list-summary{display:inline-flex;align-items:baseline;gap:6px;margin-bottom:10px;color:var(--muted);font-size:13px}.model-list-summary strong{color:var(--text);font-size:20px}.model-provider-groups{display:grid;gap:14px}.model-provider-group{overflow:hidden;border:1px solid var(--hairline);border-radius:14px}.model-provider-group>header{display:flex;align-items:center;gap:10px;min-height:58px;padding:9px 12px;background:var(--group);border-bottom:1px solid var(--hairline)}.model-provider-group>header div{display:grid;gap:2px}.model-provider-group>header span{color:var(--muted);font-size:12px}.provider-icon,.provider-icon svg{display:block;width:38px;height:38px;flex:0 0 38px}.provider-icon svg rect{fill:var(--surface-solid);stroke:var(--hairline)}.provider-icon svg text{fill:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:17px;font-weight:800}.provider-icon svg path{fill:currentColor}.provider-icon-google svg text{fill:#4285f4}.provider-icon-openai{color:var(--text)}.provider-icon-deepseek,.provider-icon-deepseek svg,.provider-icon-deepseek svg path{color:#4d6bfe;fill:#4d6bfe}.provider-icon-openrouter svg text{fill:#ef4444}.provider-icon-groq svg text{fill:#f55036}.provider-icon-moonshot svg text{fill:#16a34a}.model-compact-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(560px,1fr))}.model-compact-row{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;gap:9px;min-width:0;min-height:78px;padding:12px;border-bottom:1px solid var(--hairline)}.model-compact-row:last-child{border-bottom:0}.model-compact-main{min-width:0}.model-compact-main strong,.model-compact-main small{display:block;min-width:0;overflow-wrap:anywhere}.model-compact-main small{margin-top:3px;color:var(--muted);font-size:12px;line-height:1.35}.model-compact-main span{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px}.model-compact-main em{max-width:120px;overflow:hidden;padding:3px 7px;color:var(--muted);font-size:11px;font-style:normal;text-overflow:ellipsis;white-space:nowrap;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:999px}.model-row-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0;flex-wrap:wrap}.model-row-actions .compact-button{min-height:32px;padding-inline:11px}.model-row-actions{gap:6px}.model-row-actions .icon-button{width:32px;min-height:32px;color:var(--muted);background:transparent;border-color:transparent}.model-recommended-mark{padding:4px 8px;color:var(--orange);background:color-mix(in srgb,var(--orange) 10%,transparent);border-radius:999px;font-size:11px;font-weight:700}.model-row-menu{position:relative}.model-row-menu>summary{width:32px;min-height:32px;color:var(--muted);line-height:27px;text-align:center;letter-spacing:1px;list-style:none;background:transparent;border:1px solid transparent;border-radius:10px;cursor:pointer}.model-row-menu>summary::-webkit-details-marker{display:none}.model-row-menu>summary:hover{color:var(--text);background:var(--group)}.model-row-menu>div{position:absolute;right:0;bottom:calc(100% + 6px);z-index:8;display:grid;width:max-content;gap:2px;padding:6px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:var(--shadow)}.model-row-menu button{min-height:34px;padding:0 10px;color:var(--text);text-align:left;background:transparent;border:0;border-radius:8px;cursor:pointer;font-size:13px}.model-row-menu button:hover{background:var(--group)}.model-row-menu button.is-danger{color:var(--red)}.model-row-menu button.is-danger:hover{background:color-mix(in srgb,var(--red) 10%,var(--surface-solid))}.settings-tabs{display:flex;flex-wrap:wrap;width:fit-content;max-width:100%;padding:4px;gap:2px;overflow-x:auto;background:var(--group);border-radius:14px}.settings-tabs button{display:inline-flex;flex:0 0 auto;align-items:center;min-height:34px;padding:0 12px;border-radius:10px}.settings-tabs button small{display:none}.settings-tab-note{display:flex;align-items:baseline;gap:8px;min-height:18px;color:var(--muted);font-size:13px}.settings-tab-note strong{color:var(--text);font-size:14px}.logs-table{grid-template-columns:minmax(280px,1.55fr) minmax(220px,1fr) minmax(180px,.9fr) 82px}.logs-layout{display:block}.log-entry .table-row{min-height:58px}.log-entry .table-row>span:nth-child(2),.log-entry .table-row>span:nth-child(3){overflow:hidden;color:var(--muted);text-overflow:ellipsis;white-space:nowrap}.log-inspector{position:relative;top:auto;grid-template-columns:minmax(220px,.8fr) minmax(0,1.6fr) auto;align-items:start;margin-top:14px;padding:16px;border-radius:16px}.log-inspector header{padding:6px 14px 6px 0;border-right:1px solid var(--hairline);border-bottom:0}.log-detail{grid-template-columns:repeat(4,minmax(0,1fr))}.log-detail>div{padding:9px 10px;border-radius:10px}.log-actions{align-self:center;justify-content:flex-end}@media(max-width:980px){.log-inspector{grid-template-columns:1fr}.log-inspector header{padding:0 0 12px;border-right:0;border-bottom:1px solid var(--hairline)}.log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}}.logs-layout.has-detail{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(360px,.75fr);gap:14px;align-items:start}.logs-layout.has-detail .log-inspector{position:sticky;top:92px;display:grid;grid-template-columns:1fr;margin-top:0;padding:16px}.logs-layout.has-detail .log-inspector header{padding:0 0 12px;border-right:0;border-bottom:1px solid var(--hairline)}.logs-layout.has-detail .log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:980px){.logs-layout.has-detail{grid-template-columns:1fr}.logs-layout.has-detail .log-inspector{position:static}}@media(max-width:720px){.settings-tabs{flex-wrap:nowrap;width:100%}.settings-tab-note{align-items:flex-start;flex-direction:column;gap:2px}}.pager{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:12px}.pager span{color:var(--muted);font-size:13px;font-weight:700}.model-create-form{display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) auto;gap:10px;align-items:center}.model-create-form input,.model-create-form select{width:100%;min-width:0;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-create-form select{appearance:none}.model-create-form input:focus,.model-create-form select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-create-wide{grid-column:span 2}.model-create-message{grid-column:1 / -1;min-height:18px;color:#ff3b30;font-size:13px}.drawing-channel-models{display:flex;flex-wrap:wrap;gap:8px}.drawing-channel-models span{max-width:100%;padding:7px 10px;color:var(--muted);font-size:12px;font-weight:750;background:var(--group);border:1px solid var(--hairline);border-radius:999px;overflow-wrap:anywhere}.model-card{display:grid;gap:12px;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.model-card.featured{min-height:210px}.model-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.model-card-head strong,.model-card-head span{display:block}.model-card-head span{margin-top:4px;color:var(--muted);font-size:13px}.model-card p{color:var(--muted);line-height:1.55}.model-card-actions{display:flex;justify-content:flex-end;gap:8px}.alias-row,.model-meta{display:flex;flex-wrap:wrap;gap:8px}.alias-row span,.model-meta span{display:inline-flex;align-items:center;min-height:28px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px;font-weight:700}.model-meta span{color:var(--muted);font-weight:650}.model-id{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:42px;padding:0 0 0 12px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.model-id code{overflow:hidden;color:var(--text);text-overflow:ellipsis;white-space:nowrap}.panel-toolbar{margin-bottom:12px}.search-box{display:flex;align-items:center;gap:8px;width:100%;height:42px;padding:0 13px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px}.app-shell[data-theme=dark] .search-box,.app-shell[data-theme=dark] .model-list-toolbar input,.app-shell[data-theme=dark] .model-create-form input,.app-shell[data-theme=dark] .model-create-form select,.app-shell[data-theme=dark] .channel-form-grid input,.app-shell[data-theme=dark] .channel-form-grid textarea,.app-shell[data-theme=dark] .channel-editor input,.app-shell[data-theme=dark] .provider-picker-trigger,.app-shell[data-theme=dark] .key-editor-grid input,.app-shell[data-theme=dark] .settings-form-grid input,.app-shell[data-theme=dark] .settings-form-grid textarea,.app-shell[data-theme=dark] .maintenance-control input,.app-shell[data-theme=dark] .bulk-action-bar input,.app-shell[data-theme=dark] .auth-default-balance input{background:#7676801f;border-color:transparent}.search-box input{width:100%;border:0;outline:0;background:transparent;color:var(--text)}.search-box input::placeholder{color:var(--muted)}.table{display:grid;overflow:hidden;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .table{background:#1c1c1eb8;border-color:#ffffff0d}.table:has(.channel-editor){overflow:visible}.table-head,.table-row{display:grid;gap:12px;align-items:center;min-height:var(--row-height);padding:0 14px;text-align:left}.table-head{color:var(--muted);font-size:12px;font-weight:700;background:var(--group);border-bottom:1px solid var(--hairline)}.app-shell[data-theme=dark] .table-head{background:#7676801a;border-bottom-color:#ffffff0d}.table-row{width:100%;color:var(--text);background:transparent;border-bottom:1px solid var(--hairline)}.app-shell[data-theme=dark] .table-row{border-bottom-color:#ffffff0d}.table-row small{display:block}.table-row:last-child{border-bottom:0}button.table-row{cursor:pointer}button.table-row:hover{background:var(--group)}.app-shell[data-theme=dark] button.table-row:hover,.app-shell[data-theme=dark] .log-entry .table-row:hover,.app-shell[data-theme=dark] .log-entry .table-row.selected{background:#7676801f}.users-table{grid-template-columns:22px minmax(220px,1fr) 86px minmax(120px,.45fr) 68px}.users-table>span:nth-child(4),.users-table>span:nth-child(5){justify-self:end;text-align:right}.users-table.table-row>span:nth-child(4){max-width:100%;overflow:hidden;font-variant-numeric:tabular-nums;text-overflow:ellipsis}.users-table>input[type=checkbox]{width:16px;height:16px;margin:0;accent-color:var(--blue);cursor:pointer}.channels-table{grid-template-columns:minmax(220px,1.4fr) 90px 64px minmax(150px,.8fr) minmax(240px,1fr)}.channels-stack{display:grid;gap:14px}.channel-create-form{margin-bottom:14px}.channel-create-form .channel-form-grid{grid-template-columns:1fr 1fr;gap:14px}.channel-create-form .channel-form-wide{grid-column:1 / -1}.channel-card{display:grid;gap:14px;padding:16px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .channel-card,.app-shell[data-theme=dark] .model-card,.app-shell[data-theme=dark] .log-inspector,.app-shell[data-theme=dark] .settings-group,.app-shell[data-theme=dark] .provider-picker-menu{background:#1c1c1eb8;border-color:#ffffff0f}.channel-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.channel-card-head>div:first-child{min-width:0}.channel-card-head-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;flex-shrink:0}.channel-card-head strong,.channel-card-head span{display:block}.channel-card-head span{margin-top:4px;color:var(--muted);font-size:13px}.channel-card-head small{display:block;max-width:100%;margin-top:6px;color:var(--muted);font-size:12px;line-height:1.45;overflow-wrap:anywhere}.provider-chip-grid{display:flex;flex-wrap:wrap;gap:8px}.provider-chip-grid button{min-height:34px;padding:0 12px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;cursor:pointer;font-weight:750}.provider-chip-grid button.selected{color:var(--text);background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 42%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 30%,transparent)}.stream-mode-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.stream-mode-grid button{display:grid;gap:3px;min-height:58px;padding:9px 11px;color:var(--muted);text-align:left;background:var(--group);border:1px solid var(--hairline);border-radius:14px;cursor:pointer}.stream-mode-grid button strong{color:var(--text);font-size:14px}.stream-mode-grid button span{overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.stream-mode-grid button.selected{background:var(--surface-solid);border-color:color-mix(in srgb,var(--blue) 42%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 30%,transparent)}.app-shell[data-theme=dark] .provider-chip-grid button.selected,.app-shell[data-theme=dark] .stream-mode-grid button.selected{background:#ffffff1f;border-color:transparent;box-shadow:none}.channel-form-grid{display:grid;grid-template-columns:1.4fr .5fr .7fr;gap:12px}.channel-form-grid label{display:grid;min-width:0;gap:7px;color:var(--muted);font-size:13px;font-weight:700}.channel-model-field{display:grid;min-width:0;gap:7px}.field-label-row{display:flex;align-items:center;justify-content:space-between;gap:10px;color:var(--muted);font-size:13px;font-weight:700}.field-label-row small{font-size:12px;font-weight:700}.field-label-row .model-pull-button{min-height:28px;padding:0 12px;color:var(--blue);background:color-mix(in srgb,var(--blue) 10%,transparent);border:1px solid color-mix(in srgb,var(--blue) 26%,transparent);border-radius:999px;font-size:12.5px;font-weight:650;white-space:nowrap;cursor:pointer;transition:background .12s ease,transform .1s ease}.field-label-row .model-pull-button:hover{background:color-mix(in srgb,var(--blue) 16%,transparent)}.field-label-row .model-pull-button:active{transform:scale(.97)}.channel-form-wide{grid-column:span 2}.channel-billing-note{grid-column:1 / -1;color:var(--muted);font-size:12px}.channel-form-grid input,.channel-form-grid textarea{width:100%;min-width:0;min-height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.channel-form-grid textarea{min-height:72px;padding:10px 12px;resize:vertical;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.channel-form-grid input:focus,.channel-form-grid textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.channel-model-actions{display:flex;flex-wrap:wrap;gap:8px}.channel-card-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:10px}.channel-card-actions .model-create-message{flex:1;min-width:180px}.channel-editor{align-items:start;padding-block:12px}.channel-editor input,.provider-picker-trigger{width:100%;min-width:0;height:36px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.provider-picker{position:relative;z-index:2}.provider-picker-trigger{display:grid;grid-template-columns:minmax(0,1fr) 12px;align-items:center;gap:8px;text-align:left;cursor:pointer}.provider-picker-trigger span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.provider-picker-trigger i{width:7px;height:7px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:translateY(-2px) rotate(45deg)}.provider-picker-menu{position:absolute;top:calc(100% + 6px);left:0;display:grid;width:min(240px,70vw);max-height:280px;padding:6px;overflow:auto;background:color-mix(in srgb,var(--surface-solid) 94%,transparent);border:1px solid var(--hairline);border-radius:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.provider-picker-menu button{min-height:34px;padding:0 10px;color:var(--text);background:transparent;border-radius:9px;text-align:left;cursor:pointer}.provider-picker-menu button:hover,.provider-picker-menu button.selected{background:var(--group)}.provider-picker-menu button.selected{color:var(--blue);font-weight:800}.channel-editor strong{display:block;margin-bottom:8px}.channel-actions{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center}.logs-table{grid-template-columns:minmax(210px,1.35fr) minmax(170px,1fr) minmax(150px,.9fr) 78px 78px 86px 80px}.logs-layout{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(420px,.75fr);gap:14px;align-items:start}.logs-toolbar{display:grid;grid-template-columns:minmax(260px,1fr) auto auto;align-items:center;gap:12px;margin-bottom:14px}.log-status-filter{display:flex;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:10px}.log-status-filter button{min-height:32px;padding:0 12px;color:var(--muted);background:transparent;border-radius:7px;cursor:pointer}.log-status-filter button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 3px #0000001f}.log-entry+.log-entry{border-top:1px solid var(--hairline)}.log-entry .table-row{border:0;cursor:pointer}.log-entry .table-row:hover,.log-entry .table-row.selected{background:var(--group)}.log-inspector{position:sticky;top:92px;display:grid;gap:14px;min-width:0;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.app-shell[data-theme=dark] .flow-step{background:#7676801a;border-color:transparent}.log-inspector header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:12px;border-bottom:1px solid var(--hairline)}.log-inspector header div{display:grid;gap:4px;min-width:0}.log-inspector header span,.empty-inspector{color:var(--muted);font-size:13px}.app-shell[data-theme=dark] .sidebar-footer{background:#7676801f;border:0}.log-inspector header strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.empty-inspector{min-height:180px;place-items:center}.log-detail{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.log-detail>div{display:grid;gap:5px;min-width:0;padding:12px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.app-shell[data-theme=dark] .log-detail>div,.app-shell[data-theme=dark] .user-summary-strip span,.app-shell[data-theme=dark] .model-provider-group,.app-shell[data-theme=dark] .model-provider-filter button,.app-shell[data-theme=dark] .model-id,.app-shell[data-theme=dark] .alias-row span,.app-shell[data-theme=dark] .model-meta span{background:#7676801a;border-color:transparent}.log-detail span{color:var(--muted);font-size:12px}.log-detail strong{overflow:hidden;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.log-actions{display:flex;justify-content:flex-end;gap:8px}.detail-stack{display:grid;gap:14px}.user-hero{display:grid;grid-template-columns:52px 1fr auto;align-items:center;gap:12px;padding:4px 2px 16px;border-bottom:1px solid var(--hairline)}.user-hero h2{margin-bottom:3px;font-size:21px}.user-hero p{color:var(--muted);font-size:13px}.avatar{display:grid;place-items:center;width:52px;height:52px;color:#fff;background:var(--blue);border-radius:50%;font-weight:800;box-shadow:inset 0 1px #ffffff4d}.settings-group{overflow:hidden;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:16px;padding:4px 16px;box-shadow:0 1px 3px #0000000a}.app-shell[data-theme=dark] .settings-group{box-shadow:0 1px 2px #0003}.registration-mode-control{display:inline-grid;grid-auto-flow:column;gap:3px;padding:3px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.registration-mode-control button{min-width:74px;height:30px;padding:0 10px;color:var(--muted);background:transparent;border-radius:999px;font-weight:700;cursor:pointer}.registration-mode-control button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 4px #0000001f}.settings-layout{display:grid;gap:20px}.settings-tabs{display:flex;flex-wrap:wrap;gap:6px;width:fit-content;max-width:100%;padding:5px;overflow-x:auto;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.settings-tabs button{display:flex;align-items:center;gap:6px;min-width:0;min-height:40px;padding:0 14px;color:var(--muted);text-align:left;background:transparent;border-radius:11px;cursor:pointer;transition:color .14s ease,background .14s ease,box-shadow .14s ease}.settings-tabs button:hover:not(.selected){color:var(--text);background:color-mix(in srgb,var(--surface-solid) 50%,transparent)}.settings-tabs button.selected{color:var(--text);background:var(--surface-solid);box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.settings-tabs strong,.settings-tabs small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.settings-tabs strong{font-size:13px;font-weight:700}.settings-tabs small,.settings-tab-note{display:none}.discord-settings{display:grid;gap:18px}.discord-toggle-row,.settings-save-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.discord-toggle-row{min-height:56px;padding:0 2px 16px;border-bottom:1px solid var(--hairline)}.discord-toggle-row strong,.discord-toggle-row span{display:block}.discord-toggle-row span,.settings-save-row span{margin-top:3px;color:var(--muted);font-size:13px}.backup-actions label{display:inline-flex;align-items:center;cursor:pointer}.backup-actions input{display:none}.channel-import-actions{display:flex;align-items:center;flex-wrap:wrap;gap:10px}.channel-import-actions label{cursor:pointer}.channel-import-actions input,.channel-card-actions input[type=file]{display:none}.account-pool-list{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));margin-top:14px}.account-filter-bar{display:flex;flex-wrap:wrap;gap:7px;margin:10px 0 2px}.account-filter-bar button{padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--muted);cursor:pointer;font:inherit;font-size:12px}.account-filter-bar input{min-width:180px;flex:1 1 220px;padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--text);font:inherit;font-size:12px}.account-filter-bar select{padding:5px 9px;border:1px solid var(--hairline);border-radius:999px;background:var(--control, var(--group));color:var(--text);font:inherit;font-size:12px}.app-shell[data-theme=dark] .account-filter-bar select,.app-shell[data-theme=dark] .account-filter-bar input{background:#7676802e;border-color:#ffffff1a;color:#f5f5f7}.account-filter-bar button.selected{border-color:var(--accent);color:var(--accent)}.channel-capability-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}.channel-capability-tags span{padding:2px 7px;border:1px solid var(--hairline);border-radius:999px;color:var(--muted);font-size:11px}.account-pool-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:12px;padding:10px 12px;border:1px solid var(--hairline);border-radius:12px;background:var(--control)}.account-pool-main{display:grid;gap:8px;min-width:0}.account-pool-main>div{display:grid;gap:3px;min-width:0}.account-pool-title{display:flex;align-items:center;gap:8px;min-width:0}.account-pool-title strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-pool-main>div>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:12px}.account-pool-meta{display:flex;flex-shrink:0;align-items:center;gap:8px;justify-content:flex-end}.account-pool-more{display:flex;align-items:center;justify-content:space-between;gap:12px;grid-column:1 / -1;padding:6px 2px 0}.account-pool-more-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.account-pool-more-actions .secondary-button{flex-shrink:0}.quota-bars{display:grid;gap:6px}.quota-bar{display:grid;gap:4px}.quota-bar-label{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12px}.quota-bar-label strong{color:var(--text)}.quota-bar-track{height:5px;overflow:hidden;border-radius:999px;background:var(--hairline)}.quota-bar-track span{display:block;height:100%;border-radius:inherit;background:var(--green)}.key-editor{display:grid;gap:14px;padding:16px;border:1px solid var(--hairline);border-radius:22px;background:var(--surface-solid)}.app-shell[data-theme=dark] .key-editor{background:#1c1c1eb8;border-color:#ffffff0f}.key-editor+.key-editor{margin-top:12px}.key-editor-collapsible{gap:0;padding:0;overflow:hidden;border-radius:16px}.key-editor-collapsible[open]{gap:0}.key-editor-collapsible>summary{min-height:74px;padding:14px 16px;cursor:pointer;list-style:none}.key-editor-collapsible>summary::-webkit-details-marker{display:none}.key-editor-collapsible[open]>summary{border-bottom:1px solid var(--hairline)}.key-editor-body{display:grid;gap:14px;padding:16px}.key-expand-hint{padding:5px 10px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px}.key-editor-collapsible[open] .key-expand-hint:after{content:"中"}.key-editor-head{display:flex;align-items:center;justify-content:space-between;gap:16px}.key-editor-head strong,.key-editor-head span{display:block}.key-editor-head span{margin-top:4px;color:var(--muted);font-size:13px}.key-editor-grid{display:grid;grid-template-columns:minmax(160px,.8fr) minmax(240px,1.4fr) minmax(180px,1fr) minmax(140px,.8fr);gap:12px}.key-editor-grid label{display:grid;gap:7px;color:var(--muted);font-size:13px}.key-editor-grid input{width:100%;min-width:0;height:40px;padding:0 12px;color:var(--text);color-scheme:dark;background:var(--group);border:1px solid var(--hairline);border-radius:14px;outline:none}.key-editor-grid input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.key-editor-grid input::placeholder{color:var(--muted);opacity:.72}.key-editor-actions{display:flex;gap:8px;justify-content:flex-end}.settings-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.settings-form-grid label{display:grid;min-width:0;gap:7px;color:var(--muted);font-size:13px}.settings-form-grid input{width:100%;min-width:0;height:44px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.settings-form-grid input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-form-grid textarea{width:100%;min-width:0;min-height:88px;padding:10px 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none;resize:vertical;font:inherit;line-height:1.5;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.settings-form-grid textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-form-grid small{color:var(--muted);font-size:12px;line-height:1.45}.settings-form-grid input::placeholder{color:var(--muted);opacity:.72}.settings-form-wide{grid-column:1 / -1}.settings-save-row{min-height:44px}.settings-save-row .primary-button:disabled{cursor:wait;opacity:.58}.setting{min-height:52px}.setting span{color:var(--muted);font-size:14px}.setting-value{display:flex;align-items:center;gap:10px}.setting-value strong{color:var(--text);font-size:14px;font-weight:600}.setting>span small{display:block;margin-top:3px;color:var(--muted);font-size:12px}.auth-default-balance input{width:130px}.check-in-settings-row{align-items:center}.check-in-reward-inputs{display:grid;grid-template-columns:repeat(2,120px);gap:10px}.check-in-reward-inputs label{display:grid;gap:5px;color:var(--muted);font-size:12px}.check-in-reward-inputs input{width:100%;height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.check-in-reward-inputs input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.maintenance-control input{width:150px;height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.maintenance-control input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.settings-save-row{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding-top:12px;border-top:1px solid var(--hairline)}.settings-save-row span{margin-right:auto;color:var(--muted);font-size:13px}.ios-switch{position:relative;flex:0 0 auto;width:49px;height:30px;padding:2px;background:#d1d1d6;border-radius:999px;cursor:pointer;transition:background .16s ease}.ios-switch span{display:block;width:26px;height:26px;margin:0;background:#fff;border-radius:50%;box-shadow:0 2px 5px #0000003d;transition:transform .16s ease}.ios-switch.is-on{background:var(--green)}.ios-switch.is-on span{transform:translate(19px)}.action-row{display:flex;flex-wrap:wrap;gap:10px}.balance-adjuster{display:grid;gap:12px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.balance-adjuster-title,.balance-adjuster-actions{display:flex;align-items:center;gap:10px}.balance-adjuster-title{justify-content:space-between}.balance-adjuster-title span,.balance-adjuster-actions span,.balance-adjuster-fields label>span{color:var(--muted);font-size:12px}.balance-adjuster-fields{display:grid;grid-template-columns:110px minmax(0,1fr);gap:10px}.balance-adjuster-fields label{display:grid;gap:6px}.balance-adjuster-fields input{width:100%;min-width:0;height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.balance-adjuster-fields input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.balance-adjuster-actions span{min-width:0;overflow-wrap:anywhere}.empty{display:grid;place-items:center;min-height:160px;color:var(--muted);background:var(--group);border:1px dashed var(--hairline-strong);border-radius:18px}.toast{position:fixed;left:50%;bottom:28px;transform:translate(-50%);padding:10px 14px;color:#fff;background:#1d1d1feb;border-radius:999px;font-size:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.secret-dialog-backdrop{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:20px;background:#0000006b;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}.secret-dialog{display:grid;gap:18px;width:min(520px,100%);padding:22px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px;box-shadow:var(--shadow)}.secret-dialog>p{color:var(--muted);line-height:1.55}.secret-dialog code{overflow-x:auto;padding:13px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;white-space:nowrap}.secret-dialog-actions{display:flex;justify-content:flex-end;gap:10px}.auth-page,.account-page{--bg: #f2f2f7;--surface-solid: #ffffff;--group: #f9f9fb;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .16);--blue: #007aff;--green: #34c759;--shadow: 0 18px 45px rgba(0, 0, 0, .08);min-height:100vh;color:var(--text);background:var(--bg)}.auth-page[data-theme=dark],.account-page[data-theme=dark]{--bg: #000000;--surface-solid: #1c1c1e;--group: #2c2c2e;--text: #f5f5f7;--muted: #a1a1aa;--hairline: rgba(255, 255, 255, .12);--shadow: 0 24px 60px rgba(0, 0, 0, .36)}.auth-topbar,.account-topbar{display:flex;align-items:center;justify-content:space-between;width:min(1120px,calc(100% - 40px));min-height:76px;margin:0 auto;border-bottom:1px solid var(--hairline)}.auth-brand{display:inline-flex;align-items:center;gap:10px;padding:0;color:var(--text);background:transparent;cursor:pointer}.auth-brand .brand-mark{width:36px;height:36px;border-radius:10px}.auth-stage{display:grid;grid-template-columns:minmax(0,.9fr) minmax(360px,1fr);align-items:start;width:min(920px,calc(100% - 40px));gap:72px;margin:0 auto;padding:72px 0}.auth-intro{padding-top:24px}.auth-intro>span{color:var(--blue);font-size:13px;font-weight:700}.auth-intro h1{margin:10px 0 14px;font-size:42px}.auth-intro p{max-width:390px;color:var(--muted);line-height:1.65}.auth-form{display:grid;gap:15px;padding:24px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px;box-shadow:var(--shadow)}.auth-form label{display:grid;gap:7px;color:var(--muted);font-size:13px}.auth-form input,.auth-form select{width:100%;height:46px;padding:0 12px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:14px;outline:none}[data-theme=dark] .auth-form input,[data-theme=dark] .auth-form select{color-scheme:dark;background:var(--group)}.auth-form input:focus,.auth-form select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.setup-options{display:grid;gap:12px;padding:14px;border:1px solid var(--hairline);border-radius:18px;background:var(--group)}.setup-options .setting{padding:0;border:0}.setup-options label{gap:7px}.auth-message{min-height:18px;color:#ff3b30;font-size:13px}.auth-submit,.discord-login-button{min-height:44px;width:100%}.auth-submit:disabled{cursor:wait;opacity:.58}.discord-login-button{display:grid;place-items:center;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-weight:700;text-decoration:none}.auth-discord-register{display:grid;gap:10px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.auth-discord-register span{color:var(--muted);font-size:13px;line-height:1.5}.auth-switch{display:flex;justify-content:center}.auth-switch button{padding:6px 10px;color:var(--blue);background:transparent;cursor:pointer}.account-actions,.account-section-title,.account-heading{display:flex;align-items:center;justify-content:space-between;gap:14px}.account-section-title>div{display:grid;gap:3px}.account-content{display:grid;width:min(1120px,calc(100% - 40px));gap:18px;margin:0 auto;padding:42px 0 72px}.account-heading{padding-bottom:18px;border-bottom:1px solid var(--hairline)}.account-balance{text-align:right}.account-balance span,.account-balance strong{display:block}.account-balance span{color:var(--muted);font-size:13px}.account-balance strong{margin-top:4px;font-size:26px}.account-section{display:grid;gap:16px;padding:20px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.check-in-section{overflow:hidden;background:radial-gradient(circle at 100% 0,color-mix(in srgb,var(--blue) 22%,transparent),transparent 48%),var(--glass);border:1px solid var(--glass-border);box-shadow:var(--glass-shadow);-webkit-backdrop-filter:blur(26px) saturate(180%);backdrop-filter:blur(26px) saturate(180%)}.check-in-section .account-section-title>div{display:grid;gap:4px}.check-in-section .eyebrow,.check-in-section h2{margin:0}.check-in-section .primary-button:disabled{cursor:default;opacity:.62}.check-in-summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.check-in-summary>div{display:grid;gap:6px;padding:14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.check-in-summary span,.check-in-note{color:var(--muted);font-size:13px}.check-in-summary strong{font-size:15px}.check-in-note{margin:0;line-height:1.5}.check-in-message{color:var(--blue)}.one-time-secret{overflow-x:auto;padding:13px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px}.account-message{color:var(--muted);font-size:13px}.account-key-list{display:grid}.account-key-list>div{display:flex;align-items:center;gap:13px;min-height:66px;padding:13px 6px;border-top:1px solid var(--hairline)}.account-key-list>div:first-child{border-top:0}.account-key-list .empty{justify-content:center}.account-key-mark{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:40px;height:40px;color:var(--blue);background:color-mix(in srgb,var(--blue) 13%,transparent);border-radius:12px}.account-key-mark .icon{width:19px;height:19px}.account-key-info{display:flex;flex-direction:column;gap:3px;flex:1 1 auto;min-width:0}.account-key-info strong{font-size:15px;font-weight:650;line-height:1.25}.account-key-info code{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:12.5px;letter-spacing:.01em;color:var(--muted);overflow-wrap:anywhere}.account-key-list .badge{flex:0 0 auto;align-self:center}.account-model-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.account-model-empty{grid-column:1 / -1;padding:26px 18px;color:var(--muted);text-align:center;font-size:13px;background:color-mix(in srgb,var(--group) 60%,transparent);border:1px dashed var(--hairline);border-radius:14px}.account-model-grid article{display:grid;gap:9px;min-width:0;padding:16px;background:var(--group);border:1px solid var(--hairline);border-radius:8px}.account-model-grid article>span,.account-model-grid article p{color:var(--muted);font-size:13px}.account-model-grid article p{line-height:1.5}.account-model-grid code{overflow:hidden;text-overflow:ellipsis}.public-home{--bg: #f4f5f8;--surface: rgba(255, 255, 255, .86);--surface-solid: #ffffff;--group: #eef1f6;--text: #1d1d1f;--muted: #6e6e73;--hairline: rgba(60, 60, 67, .16);--hairline-strong: rgba(60, 60, 67, .24);--blue: #007aff;--violet: #8b5cf6;--green: #34c759;--orange: #ff9500;--shadow: 0 28px 80px rgba(16, 24, 40, .16);--glow: rgba(0, 122, 255, .15);position:relative;min-height:100vh;padding:22px;color:var(--text);background:var(--bg);overflow:hidden}.public-home:before,.public-home:after{content:"";position:absolute;border-radius:50%;filter:blur(120px);opacity:.5;pointer-events:none;z-index:0}.public-home:before{top:-10%;right:5%;width:600px;height:600px;background:var(--glow)}.public-home:after{bottom:-15%;left:-5%;width:500px;height:500px;background:#8b5cf61f}.public-home>*{position:relative;z-index:1}.public-home[data-theme=dark]{--bg: #050508;--surface: rgba(12, 17, 24, .84);--surface-solid: #0d1117;--group: #0b1017;--text: #f5f5f7;--muted: #8f969f;--hairline: rgba(255, 255, 255, .08);--hairline-strong: rgba(255, 255, 255, .16);--shadow: 0 38px 90px rgba(0, 0, 0, .5);--glow: rgba(0, 122, 255, .25);background:var(--bg)}.public-home[data-theme=dark]:before{opacity:.35}.public-home[data-theme=dark]:after{background:#8b5cf62e;opacity:.4}.home-topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;max-width:1180px;margin:0 auto}.home-brand,.home-actions,.home-cta{display:flex;align-items:center;gap:12px}.home-brand span{display:block;margin-top:2px;color:var(--muted);font-size:13px}.home-hero{display:grid;grid-template-columns:minmax(0,.88fr) minmax(460px,.92fr);gap:clamp(38px,7vw,86px);align-items:center;max-width:1180px;min-height:calc(100vh - 250px);margin:0 auto;padding:clamp(72px,10vw,128px) 0 68px}.home-copy{display:grid;gap:22px;align-content:center}.home-kicker{width:fit-content;padding:8px 13px;color:var(--blue);background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 28%,var(--hairline));border-radius:999px;font-size:13px;font-weight:700}.home-copy h1{max-width:680px;font-size:clamp(42px,4.8vw,58px);line-height:1.08;letter-spacing:0}.home-copy h1 span{display:block;width:fit-content;color:var(--blue);white-space:nowrap}.home-copy p{max-width:620px;color:var(--muted);font-size:17px;font-weight:600;line-height:1.8}.public-home .home-cta .primary-button{gap:8px;min-height:54px;padding:0 28px;color:#fff;background:var(--blue);border-radius:16px;box-shadow:0 4px 14px #007aff59,inset 0 1px #fff3;font-size:15px;font-weight:700}.public-home .home-cta .primary-button:hover{box-shadow:0 6px 20px #007aff73,inset 0 1px #fff3}.public-home[data-theme=dark] .home-cta .primary-button{color:#111318;background:#fff;box-shadow:0 4px 16px #ffffff26,inset 0 1px #ffffff80}.public-home[data-theme=dark] .home-cta .primary-button:hover{box-shadow:0 6px 24px #ffffff38,inset 0 1px #ffffff80}.public-home .home-cta .secondary-button{min-height:54px;padding:0 24px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline-strong);border-radius:16px;box-shadow:0 2px 8px #0000000f;font-size:15px;font-weight:700}.public-home[data-theme=dark] .home-cta .secondary-button{background:#ffffff14;border-color:#ffffff1f;box-shadow:0 2px 10px #0003}.integration-row{display:grid;gap:12px;margin-top:18px;color:var(--muted);font-size:13px;font-weight:700}.integration-row>div{display:flex;flex-wrap:wrap;gap:10px}.integration-row>div span{min-height:40px;padding:11px 18px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:0 2px 6px #0000000a,inset 0 1px #fff9;transition:transform .18s ease,box-shadow .18s ease}.integration-row>div span:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014,inset 0 1px #fff9}.public-home[data-theme=dark] .integration-row>div span{background:#ffffff0f;border-color:#ffffff1a;box-shadow:0 2px 8px #0003,inset 0 1px #ffffff0d}.public-home[data-theme=dark] .integration-row>div span:hover{background:#ffffff1a;box-shadow:0 4px 16px #0000004d,inset 0 1px #ffffff14}.gateway-terminal{position:relative;overflow:hidden;min-height:500px;color:#d7dde7;background:#0a0e14;border:1px solid rgba(255,255,255,.08);border-radius:24px;box-shadow:0 0 0 1px #ffffff0d,0 25px 60px -12px #0006,0 0 40px #007aff14}.gateway-terminal:before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(255,255,255,.03) 0%,transparent 30%);pointer-events:none}.terminal-titlebar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;min-height:54px;padding:0 18px;color:#9aa5b4;background:#111821;border-bottom:1px solid rgba(255,255,255,.08);font-size:13px}.terminal-dots{display:flex;gap:6px}.terminal-dots span{width:9px;height:9px;background:#445061;border-radius:50%}.terminal-status{display:inline-flex;align-items:center;gap:8px;color:#d7dde7}.terminal-status .pulse-dot{width:8px;height:8px}.terminal-endpoint{display:flex;align-items:center;gap:12px;min-height:56px;padding:0 22px;background:#0c1118;border-bottom:1px solid rgba(255,255,255,.08)}.terminal-endpoint span{padding:4px 8px;color:var(--green);background:#34c7591f;border-radius:8px;font-size:11px;font-weight:900}.terminal-endpoint strong{overflow:hidden;color:#f2f5f9;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.terminal-body{display:grid;gap:18px;padding:22px}.terminal-block{display:grid;gap:10px}.terminal-block>span{color:#758194;font-size:12px;font-weight:900;letter-spacing:.14em}.terminal-block pre{overflow-x:auto;margin:0;padding:0;color:#8fd5ff;background:transparent;border:0;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:13px;font-weight:700;line-height:1.75}.terminal-block.response pre{color:#76e4a6}.terminal-route{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.terminal-route div{min-width:0;padding:12px;background:#111821;border:1px solid rgba(255,255,255,.08);border-radius:14px}.terminal-route span{display:block;margin-bottom:6px;color:#758194;font-size:11px;font-weight:800}.terminal-route strong{overflow:hidden;display:block;color:#f2f5f9;font-size:13px;text-overflow:ellipsis;white-space:nowrap}@keyframes status-pulse{0%{box-shadow:0 0 color-mix(in srgb,var(--green) 42%,transparent)}70%{box-shadow:0 0 0 9px color-mix(in srgb,var(--green) 0%,transparent)}to{box-shadow:0 0 color-mix(in srgb,var(--green) 0%,transparent)}}@media(prefers-reduced-motion:reduce){.pulse-dot{animation:none}}.home-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;max-width:1120px;margin:0 auto;padding-bottom:34px}.home-feature{display:grid;gap:9px;min-height:150px;padding:18px;background:var(--surface);border:1px solid var(--hairline);border-radius:24px;-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.home-feature .icon{color:var(--blue)}.home-feature span{color:var(--muted);line-height:1.5}@media(max-width:1280px){.users-layout{grid-template-columns:1fr}}@media(max-width:980px){.app-shell{grid-template-columns:1fr}.sidebar{position:fixed;inset:auto 12px 12px;z-index:30;height:auto;padding:8px;border:1px solid var(--hairline);border-radius:26px;box-shadow:var(--shadow)}.ios-window-dots,.brand,.sidebar-footer{display:none}nav{grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.nav-item{flex-direction:column;justify-content:center;gap:4px;min-height:54px;padding:0 4px;border-radius:18px;font-size:11px}.content{width:100%;padding:20px 14px calc(108px + env(safe-area-inset-bottom))}.topbar{margin:-20px -14px 20px;padding:18px 14px 14px}.metrics-grid,.split-grid,.users-layout,.flow-panel,.user-summary-strip,.channel-form-grid{grid-template-columns:1fr}.stream-mode-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.bulk-action-bar{grid-template-columns:auto 100px minmax(160px,1fr)}.bulk-group-select,.auth-default-balance select{width:100%}.channel-form-wide{grid-column:auto}.model-grid{grid-template-columns:1fr}.model-list-toolbar{align-items:stretch;flex-direction:column}.model-list-toolbar input{width:100%}.model-compact-grid{grid-template-columns:1fr}.model-compact-row,.model-compact-row:nth-child(odd),.model-compact-row:nth-last-child(-n+2){border-right:0;border-bottom:1px solid var(--hairline)}.model-compact-row:last-child{border-bottom:0}.flow-steps{grid-template-columns:repeat(4,minmax(136px,1fr));overflow-x:auto;padding-bottom:2px;scroll-snap-type:x mandatory}.flow-step{scroll-snap-align:start}.channels-table,.logs-table{grid-template-columns:minmax(140px,1.3fr) 90px 70px}.logs-toolbar{grid-template-columns:1fr auto}.logs-toolbar .search-box{grid-column:1 / -1}.logs-layout{grid-template-columns:1fr}.log-inspector{position:static}.log-detail{grid-template-columns:repeat(2,minmax(0,1fr))}.channels-table span:nth-child(4),.channels-table span:nth-child(5),.logs-table span:nth-child(3),.logs-table span:nth-child(4),.logs-table span:nth-child(5),.logs-table span:nth-child(6){display:none}}@media(max-width:900px){.home-hero,.home-grid{grid-template-columns:1fr}.home-hero{min-height:0}.model-create-form{grid-template-columns:1fr}.model-create-wide{grid-column:auto}.model-compact-grid{grid-template-columns:1fr}.model-compact-row{grid-template-columns:1fr;align-items:stretch}.model-row-actions{justify-content:flex-start;flex-wrap:wrap}.auth-stage{grid-template-columns:1fr;gap:28px;max-width:560px;padding:38px 0 64px}.auth-intro{padding-top:0}.account-model-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:680px){.app-shell{display:block;min-height:100dvh}.topbar{position:sticky;top:0;align-items:flex-start;flex-direction:column;gap:12px}.topbar-actions{width:100%;display:grid;grid-template-columns:1fr auto auto auto}.segmented-control{flex:1}.segmented-control button{min-width:0}.theme-toggle span{display:none}.theme-toggle{width:40px;padding:0}.topbar-actions .home-link{display:none}.quick-actions{display:flex;overflow-x:auto;padding-bottom:2px;scroll-snap-type:x mandatory}.bulk-action-bar{grid-template-columns:1fr 1fr}.bulk-action-bar strong,.bulk-action-bar input[aria-label=调整原因]{grid-column:1 / -1}.balance-adjuster-fields{grid-template-columns:1fr}.user-filter-row{width:100%;overflow-x:auto}.user-filter-row button{flex:1 0 auto}.auth-default-balance{width:100%}.auth-default-balance input{flex:1;width:auto}.quick-action{min-width:132px;scroll-snap-align:start}.settings-form-grid{grid-template-columns:1fr}.settings-form-wide{grid-column:auto}.settings-save-row{align-items:stretch;flex-direction:column}.settings-save-row .primary-button{width:100%}.auth-topbar,.account-topbar,.auth-stage,.account-content{width:min(100% - 28px,560px)}.auth-intro h1{font-size:34px}.auth-form{padding:18px}.account-model-grid,.check-in-summary{grid-template-columns:1fr}.check-in-section .account-section-title{align-items:stretch;flex-direction:column}.check-in-section .primary-button{width:100%}.check-in-reward-inputs{width:100%;grid-template-columns:repeat(2,minmax(0,1fr))}.account-heading{align-items:flex-start}.public-home{padding:14px}.home-topbar{align-items:flex-start;flex-direction:column}.home-actions{width:100%}.home-actions .primary-button{flex:1}.home-hero{gap:20px;padding:34px 0 20px}.home-copy p{font-size:16px}.home-cta{align-items:stretch;flex-direction:column}.gateway-terminal{min-height:0;border-radius:24px}.terminal-titlebar{grid-template-columns:auto 1fr}.terminal-status{grid-column:1 / -1;justify-content:center;padding:8px 12px;background:#0c1118;border:1px solid rgba(255,255,255,.08);border-radius:999px}.terminal-body,.terminal-endpoint{padding-right:18px;padding-left:18px}.terminal-block pre{font-size:12px}.terminal-route{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:560px){nav{grid-template-columns:repeat(7,minmax(0,1fr))}h1{font-size:30px}.home-copy h1 span{white-space:normal}.metrics-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.setting{align-items:flex-start;flex-direction:column}.registration-mode-control{width:100%}.registration-mode-control button{min-width:0}.hero-strip{align-items:stretch;flex-direction:column;min-height:0;padding:18px}.hero-strip strong{font-size:20px}.live-island{justify-content:center;width:100%}.flow-panel{padding:14px}.flow-steps{display:flex;overflow-x:auto}.flow-step{min-width:136px}.flow-step:not(:last-child):after{display:none}.table{gap:10px;overflow:visible;background:transparent;border:0;border-radius:0}.table-head{display:none}.table-row,.users-table,.channels-table,.logs-table{display:grid;grid-template-columns:1fr auto;gap:8px 12px;min-height:0;padding:14px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:18px}.table-row span:nth-child(n+3){display:none}.users-table.table-row{grid-template-columns:22px minmax(0,1fr) auto}.users-table.table-row>:nth-child(3){display:inline-flex}.mobile-bulk-select{display:inline-flex;width:100%}.channel-editor.channels-table{grid-template-columns:1fr}.channel-editor span:nth-child(n+3),.channel-actions{display:grid}.channel-actions{grid-template-columns:1fr}.table-head,.table-head.users-table,.table-head.channels-table,.table-head.logs-table{display:none}.panel{padding:14px;border-radius:22px}.user-hero{grid-template-columns:48px 1fr}.user-hero .badge{grid-column:1 / -1;justify-self:start}}.modal-backdrop{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;background:#00000073;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.modal-card{width:100%;max-width:520px;max-height:88vh;overflow-y:auto;padding:22px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:20px;box-shadow:0 20px 60px #00000059}.modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.modal-head strong{font-size:18px}.modal-head>div{display:grid;gap:4px}.modal-head>div>span{color:var(--muted);font-size:13px}.account-add-modal{max-width:680px}.account-add-options{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-top:20px}.account-add-option{position:relative;display:grid;justify-items:start;gap:7px;min-width:0;padding:18px;color:var(--text);text-align:left;cursor:pointer;background:var(--group);border:1px solid var(--hairline);border-radius:16px;transition:border-color .16s ease,background .16s ease,transform .16s ease}.account-add-option:hover:not(:disabled):not(.disabled){transform:translateY(-2px);background:color-mix(in srgb,var(--blue) 7%,var(--group));border-color:color-mix(in srgb,var(--blue) 36%,var(--hairline))}.account-add-option.recommended:after{content:"推荐";position:absolute;top:12px;right:12px;padding:3px 8px;color:var(--blue);font-size:11px;font-weight:700;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border-radius:999px}.account-add-option small{color:var(--muted);line-height:1.45}.account-add-option input{display:none}.account-add-option.disabled{cursor:not-allowed;opacity:.55}.account-add-icon{display:grid;width:34px;height:34px;place-items:center;color:var(--blue);font-size:13px;font-weight:800;background:color-mix(in srgb,var(--blue) 12%,var(--surface-solid));border-radius:11px}.account-add-modal .modal-actions{margin-top:18px}@media(max-width:760px){.channel-card-head{flex-direction:column}.channel-card-head-actions{width:100%;justify-content:flex-start}.account-add-options{grid-template-columns:1fr}}.oauth-steps{margin:16px 0 0;padding-left:18px;display:flex;flex-direction:column;gap:18px}.oauth-steps li{line-height:1.6}.oauth-steps label{display:block;margin-bottom:8px;font-weight:600}.oauth-steps input{width:100%;box-sizing:border-box;height:40px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:10px;font-size:14px}.oauth-link{margin-top:10px;display:flex;flex-direction:column;gap:6px}.modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.model-picker-modal{max-width:560px}.model-picker-toolbar{display:flex;align-items:center;gap:8px}.model-picker-search{flex:1 1 auto;min-width:0;height:38px;padding:0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.model-picker-search:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.model-picker-count{margin:10px 2px 8px;color:var(--muted);font-size:12.5px;font-weight:600}.model-picker-list{display:grid;gap:4px;max-height:46vh;overflow-y:auto;padding:4px;border:1px solid var(--hairline);border-radius:14px;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--muted) 55%,transparent) transparent}.model-picker-row{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:10px;cursor:pointer}.model-picker-row:hover{background:var(--group)}.model-picker-row.checked{background:color-mix(in srgb,var(--blue) 10%,var(--group))}.model-picker-row input[type=checkbox]{flex:0 0 auto;width:17px;height:17px;accent-color:var(--blue);cursor:pointer}.model-picker-name{flex:1 1 auto;min-width:0;font-size:13.5px;color:var(--text);overflow-wrap:anywhere}.model-picker-tag{flex:0 0 auto;padding:2px 8px;color:var(--blue);background:color-mix(in srgb,var(--blue) 14%,transparent);border-radius:999px;font-size:11px;font-weight:650}.model-picker-status{padding:26px 12px;color:var(--muted);text-align:center;font-size:13px}.model-picker-error{color:#d70015}.form-error{margin-top:14px;padding:10px 12px;color:#d70015;background:color-mix(in srgb,var(--red) 12%,var(--surface-solid));border:1px solid color-mix(in srgb,var(--red) 28%,var(--hairline));border-radius:10px;font-size:13px}.source-guide{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px}.source-guide-item{padding:14px 16px;background:var(--group);border:1px solid var(--hairline);border-radius:16px}.source-guide-item strong{display:block;margin-bottom:4px;font-size:14px}.source-guide-item span{color:var(--muted);font-size:13px;line-height:1.5}.channel-card-collapsible>summary{cursor:pointer;list-style:none}.channel-card-collapsible>summary::-webkit-details-marker{display:none}.channel-card-collapsible>summary:after{content:"展开";align-self:center;margin-left:10px;padding:4px 10px;color:var(--muted);font-size:12px;background:var(--group);border:1px solid var(--hairline);border-radius:999px}.channel-card-collapsible[open]>summary:after{content:"收起"}.manual-add{display:inline-block}.manual-add>summary{cursor:pointer;list-style:none}.manual-add>summary::-webkit-details-marker{display:none}.manual-add-body{margin-top:10px;padding:12px;display:flex;flex-direction:column;gap:10px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.manual-add-actions{display:flex;flex-wrap:wrap;gap:8px}.source-tag{flex:0 0 auto;padding:1px 8px;font-size:11px;font-weight:700;border-radius:999px;vertical-align:middle}.source-tag-web{color:#0a7d28;background:color-mix(in srgb,#34c759 16%,var(--surface-solid));border:1px solid color-mix(in srgb,#34c759 32%,var(--hairline))}.source-tag-manual{color:var(--muted);background:var(--group);border:1px solid var(--hairline)}@media(max-width:720px){.source-guide{grid-template-columns:1fr}.account-pool-list{grid-template-columns:minmax(0,1fr)}}.form-success{color:var(--success);font-size:13px}.authsession-field{display:grid;gap:8px;margin-top:18px;color:var(--muted);font-size:13px;font-weight:700}.authsession-field textarea{width:100%;min-height:120px;padding:12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;resize:vertical;outline:none}.authsession-field textarea:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.primary-button,.secondary-button,.danger-button,.icon-button,.theme-toggle{transition:transform .16s ease,background .16s ease,border-color .16s ease,box-shadow .16s ease}.primary-button:hover:not(:disabled){box-shadow:0 8px 20px color-mix(in srgb,var(--blue) 32%,transparent);transform:translateY(-1px)}.secondary-button:hover:not(:disabled),.icon-button:hover:not(:disabled){background:color-mix(in srgb,var(--blue) 9%,var(--surface-solid));border-color:color-mix(in srgb,var(--blue) 18%,var(--hairline))}.channel-page-intro{display:flex;align-items:center;justify-content:space-between;gap:24px;margin:-2px 0 20px;padding:18px 20px;background:linear-gradient(120deg,color-mix(in srgb,var(--blue) 10%,var(--surface-solid)),var(--surface-solid));border:1px solid color-mix(in srgb,var(--blue) 18%,var(--hairline));border-radius:16px}.channel-page-intro strong,.channel-page-intro span{display:block}.channel-page-intro strong{margin-bottom:5px;font-size:16px}.channel-page-intro>div>span{color:var(--muted);font-size:13px}.channel-page-summary{display:flex;flex:0 0 auto;gap:20px}.channel-page-summary span{color:var(--muted);font-size:12px;white-space:nowrap}.channel-page-summary b{margin-right:4px;color:var(--text);font-size:18px}.channel-toolbar{padding-bottom:14px;border-bottom:1px solid var(--hairline)}.channels-stack{gap:10px}.channel-card-collapsible{gap:0;padding:0;overflow:hidden;border-radius:16px}.channel-card-collapsible[open]{gap:18px;padding:18px}.channel-list-row{display:grid;grid-template-columns:minmax(240px,1.4fr) minmax(130px,.55fr) minmax(150px,.75fr) auto;align-items:center;gap:20px;min-height:86px;padding:14px 18px}.channel-card-collapsible[open] .channel-list-row{min-height:0;padding:0 0 18px;border-bottom:1px solid var(--hairline)}.channel-card-collapsible>.channel-list-row:after{content:none}.channel-identity strong{font-size:15px}.channel-identity span,.channel-identity small{overflow:hidden;max-width:100%;text-overflow:ellipsis;white-space:nowrap}.channel-identity span{margin-top:4px;color:var(--text);font-size:12px;font-weight:650}.channel-identity small{margin-top:4px}.channel-list-meta{display:flex;flex-wrap:wrap;gap:6px 12px;color:var(--muted);font-size:12px}.channel-list-meta b{color:var(--text)}.channel-check-result{display:grid;gap:4px;min-width:0}.channel-check-result>span{margin:0;color:var(--muted);font-size:11px}.channel-check-result b{overflow:hidden;color:var(--muted);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.channel-check-result b.is-ok{color:var(--green)}.channel-check-result b.is-error{color:var(--red)}.channel-list-status{display:flex;align-items:center;justify-content:flex-end;gap:10px}.channel-expand-hint{padding:5px 10px;color:var(--muted);background:var(--group);border:1px solid var(--hairline);border-radius:999px;font-size:12px}.channel-card-collapsible[open] .channel-expand-hint:after{content:"中"}.channel-editor-controls{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.channel-select-field{display:grid;gap:7px;color:var(--muted);font-size:13px;font-weight:700}.channel-select-field select{width:100%;min-height:40px;padding:0 34px 0 12px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:12px;outline:none}.channel-select-field select:focus{border-color:var(--blue)}.channel-choice-menu{position:relative}.channel-choice-menu>summary{display:flex;align-items:center;justify-content:space-between;min-height:40px;padding:0 12px;color:var(--text);list-style:none;background:var(--group);border:1px solid var(--hairline);border-radius:12px;cursor:pointer}.channel-choice-menu>summary::-webkit-details-marker{display:none}.channel-choice-menu>summary:after{content:"⌄";margin-left:12px;color:var(--muted)}.channel-choice-menu>summary>span{font-weight:650}.channel-choice-menu>summary>small{color:var(--muted);font-size:12px;font-weight:500}.channel-choice-menu>div{position:absolute;top:calc(100% + 7px);right:0;left:0;z-index:20;display:grid;gap:2px;padding:6px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:14px;box-shadow:var(--shadow);-webkit-backdrop-filter:blur(22px) saturate(180%);backdrop-filter:blur(22px) saturate(180%)}.app-shell[data-theme=dark] .channel-choice-menu>div{background:#2c2c2e;border-color:#ffffff1f}.channel-choice-menu button{display:grid;gap:3px;width:100%;padding:9px 10px;color:var(--text);text-align:left;background:transparent;border:0;border-radius:9px;cursor:pointer}.channel-choice-menu button strong{font-size:13px}.channel-choice-menu button span{color:var(--muted);font-size:12px}.channel-choice-menu button:hover,.channel-choice-menu button.selected{background:color-mix(in srgb,var(--blue) 10%,var(--group))}.channel-choice-menu button.selected strong{color:var(--blue)}.channel-more-actions{position:relative}.channel-more-actions>summary{min-height:36px;padding:0 12px;color:var(--muted);line-height:36px;list-style:none;background:var(--group);border:1px solid var(--hairline);border-radius:10px;cursor:pointer;font-size:13px;font-weight:700}.channel-more-actions>summary::-webkit-details-marker{display:none}.channel-more-actions>summary:after{content:"⌄";margin-left:7px}.channel-more-actions>div{position:absolute;right:0;bottom:calc(100% + 8px);z-index:4;display:grid;width:max-content;gap:6px;padding:8px;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;box-shadow:var(--shadow)}.channel-more-actions label{cursor:pointer}.channel-more-actions input{display:none}.channel-card-actions{gap:4px}.channel-card-actions>.secondary-button,.channel-card-actions .channel-more-actions>summary,.channel-model-actions .secondary-button{min-height:34px;padding-inline:10px;color:var(--muted);background:transparent;border-color:transparent;box-shadow:none}.channel-card-actions>.secondary-button:hover:not(:disabled),.channel-card-actions .channel-more-actions>summary:hover,.channel-model-actions .secondary-button:hover:not(:disabled){color:var(--text);background:color-mix(in srgb,var(--blue) 9%,var(--group));border-color:transparent}.channel-card-actions>.primary-button{min-height:36px;padding-inline:15px}.channel-more-actions>summary{line-height:34px}.channel-more-actions>div{padding:6px;border-radius:14px}.channel-more-actions>div .secondary-button,.channel-more-actions>div .danger-button{justify-content:flex-start;min-height:34px;padding-inline:10px;background:transparent;border-color:transparent;border-radius:9px}.channel-more-actions>div .secondary-button:hover:not(:disabled){background:var(--group);border-color:transparent}.channel-more-actions>div .danger-button:hover:not(:disabled){background:color-mix(in srgb,var(--red) 10%,var(--surface-solid));border-color:transparent}@media(max-width:780px){.channel-page-intro{align-items:flex-start;flex-direction:column;gap:14px}.channel-list-row{grid-template-columns:minmax(0,1fr) auto;gap:12px}.channel-list-meta,.channel-check-result{grid-column:1 / -1}.channel-list-meta{order:3}.channel-check-result{order:4}.channel-list-status{grid-column:2;grid-row:1}.channel-editor-controls{grid-template-columns:1fr}}.gateway-terminal .terminal-block{opacity:0;animation:terminal-rise .5s ease-out forwards}.gateway-terminal .terminal-block.response{animation-delay:.45s}.gateway-terminal .terminal-route div{opacity:0;animation:terminal-rise .4s ease-out forwards}.gateway-terminal .terminal-route div:nth-child(1){animation-delay:.18s}.gateway-terminal .terminal-route div:nth-child(2){animation-delay:.28s}.gateway-terminal .terminal-route div:nth-child(3){animation-delay:.38s}.gateway-terminal .terminal-route div:nth-child(4){animation-delay:.48s}.terminal-caret{display:inline-block;width:7px;height:15px;margin-left:2px;vertical-align:text-bottom;background:#76e4a6;border-radius:1px;animation:terminal-caret-blink 1.1s step-end infinite}@keyframes terminal-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes terminal-caret-blink{0%,50%{opacity:1}50.01%,to{opacity:0}}@media(prefers-reduced-motion:reduce){.gateway-terminal .terminal-block,.gateway-terminal .terminal-route div{opacity:1;animation:none}.terminal-caret{animation:none}}.panel,.metric,.hero-strip,.flow-panel,.model-hero,.channel-card,.model-card,.settings-group,.account-pool-row,.model-provider-group,.model-provider-filter button,.table-row,.list-row,.channel-choice-menu button,.provider-picker-menu button,.model-row-menu button{transition:background .16s ease,border-color .16s ease,box-shadow .16s ease}button.table-row:hover,.log-entry .table-row:hover{box-shadow:inset 0 0 0 1px var(--hairline)}.metric:hover{border-color:var(--hairline-strong)}.cli-intro{margin:0 0 16px;color:var(--muted);font-size:14px;line-height:1.6}.cli-credentials{display:grid;gap:8px;margin-bottom:20px}.cli-credential{display:flex;align-items:center;gap:12px;min-height:48px;padding:10px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:12px}.cli-credential span{min-width:72px;color:var(--muted);font-size:13px;font-weight:600}.cli-credential code{flex:1;overflow:hidden;padding:0;color:var(--text);background:transparent;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.cli-credential .copy-button{display:grid;place-items:center;flex-shrink:0;width:32px;height:32px;color:var(--muted);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;cursor:pointer;transition:color .14s ease,border-color .14s ease}.cli-credential .copy-button:hover{color:var(--text);border-color:var(--hairline-strong)}.cli-credential .copy-button .icon{width:15px;height:15px}.cli-tools{display:grid;gap:10px}.cli-tool{overflow:hidden;background:var(--group);border:1px solid var(--hairline);border-radius:14px;transition:border-color .16s ease}.cli-tool[open]{border-color:var(--hairline-strong)}.cli-tool summary{display:flex;align-items:center;gap:12px;min-height:52px;padding:12px 16px;cursor:pointer;list-style:none}.cli-tool summary::-webkit-details-marker{display:none}.cli-tool summary:before{content:"";display:block;width:6px;height:6px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(-45deg);transition:transform .16s ease}.cli-tool[open] summary:before{transform:rotate(45deg)}.cli-tool summary strong{flex:1;color:var(--text);font-size:14px;font-weight:700}.cli-tool summary span{color:var(--muted);font-size:12px}.cli-tool>p,.cli-tool>pre{margin:0 16px 14px}.cli-tool>p{color:var(--muted);font-size:13px;line-height:1.55}.cli-tool>p code{padding:2px 6px;color:var(--text);background:var(--surface-solid);border-radius:5px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px}.cli-tool>pre{overflow-x:auto;padding:14px 16px;color:#8fd5ff;background:#0d1117;border-radius:10px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;font-weight:600;line-height:1.7;white-space:pre-wrap;word-break:break-all}.app-shell[data-theme=dark] .cli-tool>pre{background:#0006}.cli-tool>pre+pre{margin-top:-4px}.cli-message{margin:16px 0 0;padding:10px 14px;color:var(--green);background:color-mix(in srgb,var(--green) 8%,transparent);border-radius:10px;font-size:13px;font-weight:600}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes slide-up{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes scale-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes pop{0%{transform:scale(1)}50%{transform:scale(.95)}to{transform:scale(1)}}@keyframes toast-in{0%{opacity:0;transform:translateY(16px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.content{animation:fade-in .25s ease-out}.panel,.settings-group,.flow-panel,.hero-strip{animation:slide-up .3s ease-out backwards}.panel:nth-child(1),.settings-group:nth-child(1){animation-delay:0ms}.panel:nth-child(2),.settings-group:nth-child(2){animation-delay:50ms}.panel:nth-child(3),.settings-group:nth-child(3){animation-delay:.1s}.panel:nth-child(4),.settings-group:nth-child(4){animation-delay:.15s}.metric,.channel-card,.model-card,.cli-tool,.cli-credential{animation:slide-up .28s ease-out backwards}.metric:nth-child(1),.channel-card:nth-child(1),.model-card:nth-child(1){animation-delay:0ms}.metric:nth-child(2),.channel-card:nth-child(2),.model-card:nth-child(2){animation-delay:40ms}.metric:nth-child(3),.channel-card:nth-child(3),.model-card:nth-child(3){animation-delay:80ms}.metric:nth-child(4),.channel-card:nth-child(4),.model-card:nth-child(4){animation-delay:.12s}.metric:nth-child(5),.channel-card:nth-child(5),.model-card:nth-child(5){animation-delay:.16s}.metric:nth-child(6),.channel-card:nth-child(6),.model-card:nth-child(6){animation-delay:.2s}.table-row,.list-row{animation:fade-in .2s ease-out backwards}.primary-button,.secondary-button,.danger-button{transition:transform .12s ease,box-shadow .12s ease,background .14s ease,border-color .14s ease}.primary-button:hover,.secondary-button:hover,.danger-button:hover{transform:translateY(-1px)}.primary-button:active,.secondary-button:active,.danger-button:active{transform:translateY(0) scale(.98)}.ios-switch{transition:background .18s ease}.ios-switch span{transition:transform .2s cubic-bezier(.34,1.56,.64,1)}.metric:hover,.channel-card:hover,.model-card:hover{transform:translateY(-2px);box-shadow:0 6px 20px #00000014}.app-shell[data-theme=dark] .metric:hover,.app-shell[data-theme=dark] .channel-card:hover,.app-shell[data-theme=dark] .model-card:hover{box-shadow:0 6px 24px #00000047}.metric,.channel-card,.model-card{transition:transform .18s ease,box-shadow .18s ease,border-color .16s ease}.nav-item{transition:background .14s ease,color .14s ease,transform .1s ease}.nav-item:hover{transform:translate(2px)}.nav-item:active{transform:translate(0) scale(.98)}.settings-tabs button{transition:transform .12s ease,color .14s ease,background .14s ease,box-shadow .14s ease}.settings-tabs button:active{transform:scale(.97)}.toast{animation:toast-in .28s cubic-bezier(.34,1.25,.64,1)}.secret-dialog-backdrop{animation:fade-in .2s ease-out}.secret-dialog{animation:scale-in .25s cubic-bezier(.34,1.25,.64,1)}.copy-button,.cli-credential .copy-button{transition:transform .1s ease,color .14s ease,border-color .14s ease,background .14s ease}.copy-button:active,.cli-credential .copy-button:active{transform:scale(.9)}.channel-choice-menu>div,.provider-picker-menu>div,.model-row-menu{animation:slide-down .18s ease-out}@keyframes pulse-subtle{0%,to{opacity:1}50%{opacity:.7}}.pulse-dot{animation:pulse-subtle 2s ease-in-out infinite}.cli-tool summary{transition:background .14s ease}.cli-tool summary:hover{background:color-mix(in srgb,var(--surface-solid) 50%,transparent)}.cli-tool summary:before{transition:transform .2s cubic-bezier(.34,1.25,.64,1)}.icon{transition:transform .14s ease}button:hover .icon{transform:scale(1.08)}button:active .icon{transform:scale(.95)}.segmented-control button{transition:color .14s ease,background .14s ease,box-shadow .14s ease,transform .1s ease}.segmented-control button:active{transform:scale(.96)}.theme-toggle{transition:transform .12s ease,background .14s ease,border-color .14s ease}.theme-toggle:hover{transform:scale(1.03)}.theme-toggle:active{transform:scale(.97)}input,select,textarea{transition:border-color .14s ease,box-shadow .14s ease}.auth-form{animation:scale-in .3s cubic-bezier(.34,1.15,.64,1)}.account-section{animation:slide-up .3s ease-out backwards}.account-section:nth-child(1){animation-delay:0ms}.account-section:nth-child(2){animation-delay:80ms}.account-section:nth-child(3){animation-delay:.16s}.home-hero{animation:fade-in .4s ease-out}.home-copy{animation:slide-up .4s ease-out .1s backwards}.brand{transition:transform .14s ease}.brand:hover{transform:scale(1.02)}.quick-action{transition:transform .14s ease,background .14s ease,border-color .14s ease,box-shadow .14s ease}.quick-action:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.quick-action:active{transform:translateY(0) scale(.98)}.table-row{transition:background .12s ease,box-shadow .12s ease,transform .1s ease}button.table-row:active{transform:scale(.995)}.badge:before{transition:transform .2s ease,opacity .2s ease}.badge:hover:before{transform:scale(1.3)}.model-list-toolbar input,.user-filter-row input,.search-input{transition:border-color .16s ease,box-shadow .16s ease,background .16s ease}.model-list-toolbar input:focus,.user-filter-row input:focus,.search-input:focus{background:var(--surface-solid)}.pager button{transition:transform .1s ease,background .12s ease,border-color .12s ease}.pager button:hover:not(:disabled){transform:scale(1.05)}.pager button:active:not(:disabled){transform:scale(.95)}details summary{transition:background .14s ease,color .14s ease}details[open]>summary{color:var(--text)}.list-row{transition:background .12s ease,transform .1s ease}.list-row:hover{background:color-mix(in srgb,var(--group) 50%,transparent)}.channel-card,.model-card{animation:slide-up .25s ease-out backwards}.channel-card:nth-child(1),.model-card:nth-child(1){animation-delay:0ms}.channel-card:nth-child(2),.model-card:nth-child(2){animation-delay:30ms}.channel-card:nth-child(3),.model-card:nth-child(3){animation-delay:60ms}.channel-card:nth-child(4),.model-card:nth-child(4){animation-delay:90ms}.channel-card:nth-child(5),.model-card:nth-child(5){animation-delay:.12s}.channel-card:nth-child(6),.model-card:nth-child(6){animation-delay:.15s}.channel-card:nth-child(7),.model-card:nth-child(7){animation-delay:.18s}.channel-card:nth-child(8),.model-card:nth-child(8){animation-delay:.21s}.users-layout .table-row.selected{animation:pop .2s ease-out}.user-filter-row button,.model-filter-actions button,.log-status-filter button,.model-provider-filter button{transition:transform .1s ease,color .12s ease,background .12s ease,box-shadow .12s ease}.user-filter-row button:active,.model-filter-actions button:active,.log-status-filter button:active,.model-provider-filter button:active{transform:scale(.96)}.bulk-action-bar{animation:slide-up .2s ease-out}.secret-dialog code{animation:fade-in .3s ease-out .15s backwards}.gateway-terminal{animation:scale-in .5s cubic-bezier(.16,1,.3,1) .2s backwards}.home-kicker{animation:slide-up .35s ease-out backwards}.home-cta{animation:slide-up .4s ease-out .15s backwards}.integration-row>div span{animation:slide-up .3s ease-out backwards}.integration-row>div span:nth-child(1){animation-delay:.25s}.integration-row>div span:nth-child(2){animation-delay:.3s}.integration-row>div span:nth-child(3){animation-delay:.35s}.topbar{animation:slide-down .3s ease-out}.nav-item{animation:fade-in .25s ease-out backwards}nav .nav-item:nth-child(1){animation-delay:0ms}nav .nav-item:nth-child(2){animation-delay:30ms}nav .nav-item:nth-child(3){animation-delay:60ms}nav .nav-item:nth-child(4){animation-delay:90ms}nav .nav-item:nth-child(5){animation-delay:.12s}nav .nav-item:nth-child(6){animation-delay:.15s}nav .nav-item:nth-child(7){animation-delay:.18s}nav .nav-item:nth-child(8){animation-delay:.21s}.sidebar-footer{animation:fade-in .4s ease-out .2s backwards}input:focus,select:focus,textarea:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 15%,transparent)}.provider-icon{transition:transform .15s ease}.channel-card:hover .provider-icon,.model-card:hover .provider-icon{transform:scale(1.1)}input[type=checkbox],input[type=radio]{transition:transform .1s ease,box-shadow .1s ease}input[type=checkbox]:active,input[type=radio]:active{transform:scale(.9)}.log-inspector{animation:slide-up .25s ease-out}.model-hero{animation:slide-up .35s ease-out backwards}.flow-step{animation:slide-up .3s ease-out backwards}.flow-step:nth-child(1){animation-delay:0ms}.flow-step:nth-child(2){animation-delay:60ms}.flow-step:nth-child(3){animation-delay:.12s}.flow-step:nth-child(4){animation-delay:.18s}.hero-strip{animation:fade-in .35s ease-out backwards}.empty{animation:fade-in .3s ease-out}.account-model-grid article{animation:slide-up .25s ease-out backwards;transition:transform .15s ease,box-shadow .15s ease}.account-model-grid article:hover{transform:translateY(-2px);box-shadow:0 4px 12px #00000014}.account-model-grid article:nth-child(1){animation-delay:0ms}.account-model-grid article:nth-child(2){animation-delay:25ms}.account-model-grid article:nth-child(3){animation-delay:50ms}.account-model-grid article:nth-child(4){animation-delay:75ms}.account-model-grid article:nth-child(5){animation-delay:.1s}.account-model-grid article:nth-child(6){animation-delay:125ms}.account-key-list>div{animation:slide-up .25s ease-out backwards}.account-key-list>div:nth-child(1){animation-delay:0ms}.account-key-list>div:nth-child(2){animation-delay:40ms}.account-key-list>div:nth-child(3){animation-delay:80ms}.one-time-secret{animation:scale-in .3s cubic-bezier(.34,1.25,.64,1)}.account-balance{animation:fade-in .4s ease-out .1s backwards}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}.pulse-dot{animation:none}}.app-shell{--glass: linear-gradient(158deg, rgba(255, 255, 255, .92) 0%, rgba(255, 255, 255, .64) 100%);--glass-border: rgba(255, 255, 255, .72);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), 0 1px 2px rgba(17, 24, 39, .04), 0 12px 34px rgba(17, 24, 39, .08);background:radial-gradient(1120px 620px at 6% -8%,rgba(0,122,255,.1),transparent 58%),radial-gradient(960px 560px at 102% 2%,rgba(48,176,199,.1),transparent 56%),radial-gradient(900px 760px at 50% 118%,rgba(255,149,0,.06),transparent 60%),var(--bg)}.app-shell[data-theme=dark]{--glass: linear-gradient(158deg, rgba(58, 58, 66, .72) 0%, rgba(28, 28, 34, .6) 100%);--glass-border: rgba(255, 255, 255, .1);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .3), 0 18px 44px rgba(0, 0, 0, .48);background:radial-gradient(1120px 620px at 6% -8%,rgba(10,132,255,.18),transparent 58%),radial-gradient(960px 560px at 102% 2%,rgba(48,176,199,.15),transparent 56%),radial-gradient(900px 760px at 50% 120%,rgba(120,88,255,.14),transparent 60%),var(--bg)}.account-page,.auth-page{--glass: linear-gradient(158deg, rgba(255, 255, 255, .94) 0%, rgba(255, 255, 255, .66) 100%);--glass-border: rgba(255, 255, 255, .75);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 1px 2px rgba(17, 24, 39, .04), 0 16px 40px rgba(17, 24, 39, .09);background:radial-gradient(1080px 640px at 4% -10%,rgba(0,122,255,.12),transparent 56%),radial-gradient(940px 560px at 104% 4%,rgba(48,176,199,.1),transparent 54%),radial-gradient(880px 720px at 52% 120%,rgba(175,82,222,.07),transparent 60%),var(--bg)}.account-page[data-theme=dark],.auth-page[data-theme=dark]{--glass: linear-gradient(158deg, rgba(58, 58, 66, .7) 0%, rgba(24, 24, 30, .58) 100%);--glass-border: rgba(255, 255, 255, .12);--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 2px 6px rgba(0, 0, 0, .35), 0 22px 52px rgba(0, 0, 0, .5);background:radial-gradient(1080px 640px at 4% -10%,rgba(10,132,255,.22),transparent 56%),radial-gradient(940px 560px at 104% 4%,rgba(48,176,199,.16),transparent 54%),radial-gradient(880px 720px at 52% 122%,rgba(175,82,222,.16),transparent 60%),var(--bg)}.metric,.panel,.account-section:not(.check-in-section),.settings-group,.model-card,.channel-card,.flow-panel,.hero-strip,.model-hero,.log-inspector,.source-guide-item{background:var(--glass);border:1px solid var(--glass-border);box-shadow:var(--glass-shadow);-webkit-backdrop-filter:blur(26px) saturate(185%);backdrop-filter:blur(26px) saturate(185%)}.app-shell[data-theme=dark] .metric,.app-shell[data-theme=dark] .panel,.app-shell[data-theme=dark] .settings-group,.app-shell[data-theme=dark] .model-card,.app-shell[data-theme=dark] .channel-card,.app-shell[data-theme=dark] .flow-panel,.app-shell[data-theme=dark] .hero-strip,.app-shell[data-theme=dark] .model-hero,.app-shell[data-theme=dark] .log-inspector,.app-shell[data-theme=dark] .source-guide-item{background:var(--glass);border-color:var(--glass-border);box-shadow:var(--glass-shadow)}.group-assign-row{display:grid;gap:6px;margin-top:4px;padding:12px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.group-assign-row label{display:grid;gap:6px;color:var(--muted);font-size:12px}.group-assign-row select{height:38px;padding:0 10px;color:var(--text);background:var(--surface-solid);border:1px solid var(--hairline);border-radius:8px;outline:none}.group-assign-row select:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}.group-assign-row small{color:var(--muted);font-size:12px;line-height:1.5}.channel-group-field{display:grid;gap:8px;padding:12px 14px;background:var(--group);border:1px solid var(--hairline);border-radius:14px}.channel-group-empty{color:var(--muted);font-size:13px;line-height:1.5}.channel-group-options{display:flex;flex-wrap:wrap;gap:8px}.channel-group-options button{display:grid;gap:2px;min-width:0;padding:8px 12px;color:var(--text);text-align:left;background:var(--surface-solid);border:1px solid var(--hairline);border-radius:12px;cursor:pointer}.channel-group-options button small{color:var(--muted)}.channel-group-options button.selected{border-color:color-mix(in srgb,var(--blue) 46%,var(--hairline));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--blue) 28%,transparent)}.app-shell[data-theme=dark] .group-assign-row select,.app-shell[data-theme=dark] .channel-group-options button,.app-shell[data-theme=dark] .group-edit-fields input{background:#7676801f;border-color:transparent}.group-edit-fields{display:grid;gap:8px}.group-edit-fields input{height:38px;padding:0 10px;color:var(--text);background:var(--group);border:1px solid var(--hairline);border-radius:8px;outline:none}.group-edit-fields input:focus{border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)} diff --git a/dist/index.html b/dist/index.html index bc4ee9f..1893460 100644 --- a/dist/index.html +++ b/dist/index.html @@ -5,8 +5,8 @@ CAPI - - + +
diff --git a/src/App.tsx b/src/App.tsx index 1734f4b..b6bb05e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -279,6 +279,7 @@ type AuthSettings = { registrationEnabled: boolean; registrationMode: RegistrationMode; defaultBalance: number; + defaultGroupId: string; }; type MaintenanceSettings = { @@ -878,7 +879,7 @@ function App() { async function bulkUpdateUsers( userIds: string[], - action: "set_status" | "set_role" | "adjust_balance", + action: "set_status" | "set_role" | "adjust_balance" | "set_group", options: { value?: string; amount?: number; reason?: string } = {} ) { const data = await fetchJson<{ users: User[]; updated: number }>("/api/users/bulk", { @@ -1332,7 +1333,7 @@ function App() { {active === "drawing" && } {active === "channels" && } {active === "logs" && } - {active === "settings" && } + {active === "settings" && } {createdKeySecret && ( @@ -2015,7 +2016,7 @@ function UsersView({ onUpdate: (id: string, patch: Partial) => void; onBulkUpdate: ( ids: string[], - action: "set_status" | "set_role" | "adjust_balance", + action: "set_status" | "set_role" | "adjust_balance" | "set_group", options?: { value?: string; amount?: number; reason?: string } ) => Promise; onCreateKey: (id: string) => void; @@ -2028,6 +2029,7 @@ function UsersView({ const [selectedIds, setSelectedIds] = useState>(new Set()); const [bulkAmount, setBulkAmount] = useState("10"); const [bulkReason, setBulkReason] = useState(""); + const [bulkGroupId, setBulkGroupId] = useState(""); const [bulkBusy, setBulkBusy] = useState(false); const [balanceAmount, setBalanceAmount] = useState("10"); const [balanceReason, setBalanceReason] = useState(""); @@ -2074,7 +2076,7 @@ function UsersView({ } async function runBulk( - action: "set_status" | "adjust_balance", + action: "set_status" | "adjust_balance" | "set_group", options: { value?: string; amount?: number; reason?: string } ) { if (selectedIds.size === 0) return; @@ -2179,6 +2181,26 @@ function UsersView({ + + )}
@@ -4199,11 +4221,12 @@ function LogDetail({ log, loading, onCopy }: { log: RequestLog | null; loading: ); } -function SettingsView({ models, channels }: { models: ModelItem[]; channels: Channel[] }) { +function SettingsView({ models, channels, groups }: { models: ModelItem[]; channels: Channel[]; groups: UserGroup[] }) { const [discord, setDiscord] = useState(null); const [registrationEnabled, setRegistrationEnabled] = useState(null); const [registrationMode, setRegistrationMode] = useState("username"); const [defaultBalance, setDefaultBalance] = useState("0"); + const [defaultGroupId, setDefaultGroupId] = useState(""); const [checkInSettings, setCheckInSettings] = useState({ enabled: true, minReward: 0.1, @@ -4256,6 +4279,7 @@ function SettingsView({ models, channels }: { models: ModelItem[]; channels: Cha setRegistrationEnabled(authData.auth.registrationEnabled); setRegistrationMode(normalizeRegistrationMode(authData.auth.registrationMode)); setDefaultBalance(String(authData.auth.defaultBalance || 0)); + setDefaultGroupId(authData.auth.defaultGroupId || ""); setCheckInSettings(checkInData.checkIn); setAccount(accountData.account); setAccountUsername(accountData.account?.username || ""); @@ -4268,16 +4292,27 @@ function SettingsView({ models, channels }: { models: ModelItem[]; channels: Cha .catch(() => setMessage("设置加载失败")); }, []); - async function saveAuthSettings(nextEnabled = registrationEnabled, nextMode = registrationMode, nextDefaultBalance = Number(defaultBalance)) { + async function saveAuthSettings( + nextEnabled = registrationEnabled, + nextMode = registrationMode, + nextDefaultBalance = Number(defaultBalance), + nextDefaultGroupId = defaultGroupId + ) { if (nextEnabled === null) return; try { const data = await fetchJson<{ auth: AuthSettings }>("/api/settings/auth", { method: "PATCH", - body: JSON.stringify({ registrationEnabled: nextEnabled, registrationMode: nextMode, defaultBalance: nextDefaultBalance }) + body: JSON.stringify({ + registrationEnabled: nextEnabled, + registrationMode: nextMode, + defaultBalance: nextDefaultBalance, + defaultGroupId: nextDefaultGroupId + }) }); setRegistrationEnabled(data.auth.registrationEnabled); setRegistrationMode(normalizeRegistrationMode(data.auth.registrationMode)); setDefaultBalance(String(data.auth.defaultBalance || 0)); + setDefaultGroupId(data.auth.defaultGroupId || ""); setMessage(data.auth.registrationEnabled ? "注册设置已保存" : "已关闭用户注册"); } catch (error) { setMessage(error instanceof Error ? error.message : "注册设置保存失败"); @@ -4668,6 +4703,32 @@ response = client.chat.completions.create(
+
+ + 默认注册分组 + 新注册用户自动归入该分组,决定他们能用哪些渠道 + +
+ + +
+
)} diff --git a/src/styles.css b/src/styles.css index 92c78be..df979fd 100644 --- a/src/styles.css +++ b/src/styles.css @@ -997,7 +997,7 @@ h3 { .bulk-action-bar { display: grid; - grid-template-columns: auto 100px minmax(160px, 1fr) auto auto auto; + grid-template-columns: auto 100px minmax(160px, 1fr) auto auto auto minmax(130px, auto) auto; align-items: center; gap: 8px; margin-bottom: 12px; @@ -1007,6 +1007,49 @@ h3 { border-radius: 12px; } +.bulk-group-select { + min-width: 0; + height: 38px; + padding: 0 10px; + color: var(--text); + background: var(--surface-solid); + border: 1px solid var(--hairline); + border-radius: 8px; + outline: none; +} + +.bulk-group-select:focus { + border-color: var(--blue); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent); +} + +.app-shell[data-theme="dark"] .bulk-group-select { + background: rgba(118, 118, 128, 0.12); + border-color: transparent; +} + +.auth-default-balance select { + min-width: 0; + width: 180px; + height: 38px; + padding: 0 10px; + color: var(--text); + background: var(--surface-solid); + border: 1px solid var(--hairline); + border-radius: 8px; + outline: none; +} + +.auth-default-balance select:focus { + border-color: var(--blue); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent); +} + +.app-shell[data-theme="dark"] .auth-default-balance select { + background: rgba(118, 118, 128, 0.12); + border-color: transparent; +} + .bulk-action-bar input, .auth-default-balance input { min-width: 0; @@ -4173,6 +4216,11 @@ button.table-row:hover { grid-template-columns: auto 100px minmax(160px, 1fr); } + .bulk-group-select, + .auth-default-balance select { + width: 100%; + } + .channel-form-wide { grid-column: auto; }