khala-cli 0.4.2 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{chunk-T6RZE5IQ.mjs → chunk-6LC66VHK.mjs} +10 -7
  2. package/dist/chunk-7G2G4E4U.mjs +236 -0
  3. package/dist/chunk-AUJEUKVM.mjs +121 -0
  4. package/dist/{chunk-NUS6M27N.mjs → chunk-EW22K3JO.mjs} +445 -199
  5. package/dist/chunk-EXHCVFVH.mjs +26 -0
  6. package/dist/{chunk-CDHHFC6C.mjs → chunk-H46OG22B.mjs} +22 -6
  7. package/dist/{chunk-YP45XTOH.mjs → chunk-HB3UGIZG.mjs} +5 -5
  8. package/dist/chunk-IR3VN2ID.mjs +52 -0
  9. package/dist/{chunk-B5BFL7OD.mjs → chunk-KCJFSVDN.mjs} +55 -4
  10. package/dist/{chunk-K4MDSFHU.mjs → chunk-MBLP7LQJ.mjs} +103 -38
  11. package/dist/{chunk-RW3DXWNC.mjs → chunk-OLZ62X7S.mjs} +1 -1
  12. package/dist/chunk-P5CP32X2.mjs +170 -0
  13. package/dist/{chunk-A3LJU4JA.mjs → chunk-PXKGKVGW.mjs} +1 -1
  14. package/dist/{chunk-7MQAMABY.mjs → chunk-RSDOTTZQ.mjs} +4 -4
  15. package/dist/chunk-SN3STAO2.mjs +190 -0
  16. package/dist/{chunk-MHZWR4A3.mjs → chunk-SQXDATEC.mjs} +1 -1
  17. package/dist/chunk-T7YRVE43.mjs +238 -0
  18. package/dist/{chunk-BZ53MZEE.mjs → chunk-TZKEQIHP.mjs} +8 -4
  19. package/dist/{chunk-46PTKRZC.mjs → chunk-V4Y26O4R.mjs} +171 -113
  20. package/dist/chunk-V7M27QLT.mjs +21 -0
  21. package/dist/{chunk-2OO725IZ.mjs → chunk-Y2DRTRBJ.mjs} +3 -3
  22. package/dist/{chunk-JRZZVTQ4.mjs → chunk-Y4WVILEJ.mjs} +94 -10
  23. package/dist/khala.mjs +12 -10
  24. package/dist/web/assets/apple-touch-icon-Du9V6qit.png +0 -0
  25. package/dist/web/assets/favicon-16x16-D5waNSZD.png +0 -0
  26. package/dist/web/assets/favicon-32x32-B9Ubw1Dx.png +0 -0
  27. package/dist/web/assets/favicon-zCD0pKtT.ico +0 -0
  28. package/dist/web/assets/local-C1vz22ps.js +9 -0
  29. package/dist/web/assets/local-DdjwMERJ.css +1 -0
  30. package/dist/web/index.html +7 -2
  31. package/package.json +1 -1
  32. package/dist/chunk-N6LMHR7P.mjs +0 -455
  33. package/dist/chunk-U5ZMOPUK.mjs +0 -149
  34. package/dist/web/assets/local-CVA9799w.js +0 -9
  35. package/dist/web/assets/local-DHYvcQG0.css +0 -1
@@ -0,0 +1 @@
1
+ .kh-card{position:relative}.kh-main{container:khm / inline-size}.kh-ib{flex:0 0 auto;width:34px;height:34px;display:grid;place-items:center;border:0;border-radius:10px;background:none;color:var(--muted);cursor:pointer;position:relative;padding:0;font:inherit}.kh-ib:hover{background:var(--surface-2);color:var(--fg)}.kh-ib svg{width:18px;height:18px}.kh-ib.sm{width:28px;height:28px;border-radius:8px}.kh-ib.sm svg{width:15px;height:15px}.kh-ib.ok{color:var(--good-ink)}.kh-ib.ok:hover{background:var(--good-soft)}.kh-ib.no:hover{color:var(--block);background:var(--block-soft)}.kh-ib[aria-expanded=true]{background:var(--surface-3);color:var(--fg)}@media(pointer:coarse){.kh-ib{width:44px;height:44px}.kh-ib.sm{width:36px;height:36px}}@media(hover:hover){.kh-card [data-tip]:hover:after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);right:0;z-index:30;white-space:nowrap;font-size:.7rem;font-weight:600;line-height:1.2;letter-spacing:0;text-transform:none;padding:5px 8px;border-radius:7px;background:var(--fg);color:var(--surface);pointer-events:none}}.kh-pop{position:absolute;z-index:25;width:min(290px,calc(100% - 16px));box-sizing:border-box;padding:.75rem;border-radius:14px;background:var(--surface);border:1px solid var(--line-strong);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;gap:.65rem;animation:khPopIn .14s ease-out}.kh-pop[hidden]{display:none}.kh-pop.menu{width:auto;min-width:170px;padding:.3rem;gap:0}@keyframes khPopIn{0%{opacity:0;transform:translateY(-4px)}}.kh-pop-h{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--faint)}.kh-f{display:flex;align-items:center;justify-content:space-between;gap:.6rem;font-size:.84rem}.kh-f>span:first-child{color:var(--muted)}.kh-f.col{flex-direction:column;align-items:stretch;gap:.4rem}.kh-lk{position:relative;display:inline-flex;align-items:center;gap:4px}.kh-lk svg{width:11px;height:11px}.kh-seg{display:inline-flex;padding:2px;border-radius:9px;background:var(--surface-3);border:1px solid var(--line);flex:0 0 auto}.kh-seg button{position:relative;border:0;background:none;color:var(--muted);border-radius:7px;font:inherit;font-size:.78rem;font-weight:600;padding:4px 9px;cursor:pointer;display:grid;place-items:center;white-space:nowrap}.kh-seg button:hover{color:var(--fg)}.kh-seg button.on{background:var(--surface);color:var(--fg);box-shadow:0 1px 2px #00000040}.kh-seg.full{display:flex}.kh-seg.full button{flex:1}.kh-seg.lock{opacity:.55}.kh-seg button:disabled{cursor:default}.kh-seg.ic button{width:28px;height:24px;padding:0}.kh-seg.ic svg{width:14px;height:14px}.kh-seg.ic button.on{color:var(--accent-ink)}@media(pointer:coarse){.kh-seg.ic button{width:36px;height:32px}.kh-seg button{padding:7px 11px}}.kh-sw{width:34px;height:20px;border-radius:999px;border:0;background:var(--surface-3);box-shadow:inset 0 0 0 1px var(--line-strong);position:relative;cursor:pointer;flex:0 0 auto;padding:0}.kh-sw:before{content:"";position:absolute;top:3px;left:3px;width:14px;height:14px;border-radius:50%;background:var(--muted);transition:transform .15s,background .15s}.kh-sw[aria-checked=true]{background:var(--accent);box-shadow:none}.kh-sw[aria-checked=true]:before{transform:translate(14px);background:#fff}.kh-link,.kh-oneliner{display:flex;align-items:center;gap:.3rem;padding-left:.65rem;height:38px;border-radius:10px;background:var(--bg-2);border:1px solid var(--line)}.kh-oneliner{border-style:dashed;border-color:var(--line-strong)}.kh-link code,.kh-oneliner code{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:.74rem JetBrains Mono,monospace;color:var(--muted)}.kh-oneliner code{color:var(--fg)}.kh-link .kh-ib,.kh-oneliner .kh-ib{margin-right:4px}.kh-txt{height:36px;min-width:0;width:100%;box-sizing:border-box;border-radius:10px;border:1px solid var(--line-strong);background:var(--bg-2);color:var(--fg);padding:0 .7rem;font:inherit;font-size:.88rem;outline:none}@media(pointer:coarse){.kh-txt{font-size:16px;height:44px}}.kh-txt:focus{border-color:var(--accent-line);box-shadow:0 0 0 3px var(--accent-soft)}.kh-btn{height:34px;padding:0 .9rem;border-radius:10px;border:1px solid var(--line-strong);background:var(--surface-3);color:var(--fg);font:inherit;font-size:.84rem;font-weight:600;cursor:pointer;flex:0 0 auto}@media(pointer:coarse){.kh-btn{height:44px}}.kh-btn.pri{background:var(--accent);border-color:var(--accent);color:#fff}.kh-btn.danger{background:var(--block);border-color:var(--block);color:#fff}.kh-btn:disabled{opacity:.4;cursor:default}.kh-btn-ic{display:flex;align-items:center;justify-content:center;gap:.45rem}.kh-btn-ic svg{width:15px;height:15px}.kh-hint{font-size:.74rem;color:var(--faint);text-align:center;margin-top:-.3rem}.kh-tbtn{align-self:flex-start;border:0;background:none;padding:.2rem 0;font:inherit;font-size:.84rem;font-weight:600;color:var(--block);cursor:pointer}.kh-tbtn:hover{text-decoration:underline}.kh-sep{height:1px;background:var(--line);margin:0 -.75rem}.kh-row2{display:flex;gap:.4rem}.kh-or{display:flex;align-items:center;gap:.5rem;font-size:.7rem;color:var(--faint)}.kh-or:before,.kh-or:after{content:"";flex:1;height:1px;background:var(--line)}.kh-mi{display:flex;align-items:center;gap:.55rem;width:100%;padding:.5rem .6rem;border:0;border-radius:9px;background:none;color:var(--fg);font:inherit;font-size:.84rem;text-align:left;cursor:pointer;min-height:36px;white-space:nowrap}@media(pointer:coarse){.kh-mi{min-height:44px}}.kh-mi:hover{background:var(--surface-2)}.kh-mi svg{width:15px;height:15px;flex:0 0 auto}.kh-mi em{margin-left:auto;padding-left:.8rem;font-style:normal;font-size:.72rem;color:var(--faint)}.kh-swatch-dot{display:inline-block;width:8px;height:8px;margin-right:.35rem;border-radius:50%;vertical-align:0}.kh-mi.on{color:var(--accent-ink)}.kh-mi.danger{color:var(--block)}.kh-mi.danger:hover{background:var(--block-soft)}.kh-toast{position:absolute;left:50%;bottom:104px;z-index:30;display:flex;align-items:center;gap:.35rem;padding:.45rem .85rem;border-radius:999px;background:var(--fg);color:var(--surface);font-size:.8rem;font-weight:600;white-space:nowrap;opacity:0;transform:translate(-50%,8px);pointer-events:none;transition:opacity .18s,transform .18s}.kh-toast.on{opacity:1;transform:translate(-50%)}.kh-toast svg{width:14px;height:14px}.kh-card .kh-roster [data-tip]:hover:after{content:none}.kh-roster-tooltip{position:absolute;z-index:30;width:max-content;max-width:calc(100% - 16px);box-sizing:border-box;font-size:.7rem;font-weight:600;line-height:1.2;padding:5px 8px;border-radius:7px;background:var(--fg);color:var(--surface);pointer-events:none}.kh-roster-tooltip[hidden]{display:none}.kh-list-head{display:flex;align-items:baseline;justify-content:space-between;padding:1rem 1rem .6rem}.kh-list-head b{font-size:1.05rem;letter-spacing:-.02em}.kh-list-head span{font-size:.76rem;color:var(--muted)}.kh-list-head{align-items:center;gap:.5rem}.kh-list-head b{flex:1}.kh-search{display:flex;align-items:center;gap:.45rem;margin:0 .8rem .6rem;padding:0 .7rem;height:34px;border-radius:10px;background:var(--surface-3);color:var(--faint)}.kh-search svg{width:15px;height:15px;flex:0 0 auto}.kh-search input{flex:1;min-width:0;border:0;background:none;outline:none;color:var(--fg);font:inherit;font-size:.88rem}.kh-convos{flex:1;overflow-y:auto;padding:0 .5rem .6rem;display:flex;flex-direction:column;gap:2px}.kh-cv{display:grid;grid-template-columns:44px minmax(0,1fr);gap:.65rem;align-items:center;padding:.6rem .55rem;border-radius:12px;border:0;background:none;color:var(--fg);font:inherit;text-align:left;cursor:pointer;position:relative}.kh-cv:hover{background:var(--surface-2)}.kh-cv.is-active{background:var(--accent);color:#fff}.kh-cv.is-active .kh-cv-pv,.kh-cv.is-active .kh-cv-t time{color:#fffc}.kh-cv-av{position:relative;width:44px;height:44px}.kh-cv-av .kh-av{position:absolute;width:30px;height:30px;pointer-events:none}.kh-cv-av .kh-av:first-child{left:0;top:0}.kh-cv-av .kh-av:nth-child(2){right:0;bottom:0;border:2px solid var(--surface)}.kh-cv-av .kh-av:only-child{width:44px;height:44px}.kh-cv-av .kh-own{display:none}.kh-cv-av .kh-av img{width:15px;height:15px}.kh-cv-t{display:flex;flex-direction:column;gap:2px;min-width:0}.kh-cv-t>span:first-child{display:flex;align-items:baseline;gap:.5rem}.kh-cv-t b{flex:1;min-width:0;font-size:.9rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kh-cv-t time{flex:0 0 auto;font-size:.72rem;color:var(--faint)}.kh-cv-pv{font-size:.8rem;color:var(--muted);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.kh-cv.unread b{font-weight:700}.kh-cv.unread:before{content:"";position:absolute;left:-1px;top:50%;width:8px;height:8px;margin-top:-4px;border-radius:50%;background:var(--accent)}.kh-cv.unread.is-active:before{background:#fff}.kh-cv-empty{padding:1.2rem;text-align:center;color:var(--faint);font-size:.84rem}.kh-cv.dead{opacity:.55}@media(max-width:760px){.kh-cv{padding:.7rem .55rem;min-height:60px}.kh-search input{font-size:16px}}.kh-cv-skel{cursor:default}.kh-cv-skel:hover{background:none}.kh-cv-skel .kh-cv-av,.kh-cv-skel .kh-cv-t>span{border-radius:50%;background:linear-gradient(100deg,var(--surface-3) 30%,var(--surface-2) 50%,var(--surface-3) 70%);background-size:200% 100%;animation:khSkel 1.4s ease-in-out infinite}.kh-cv-skel .kh-cv-t{gap:8px}.kh-cv-skel .kh-cv-t>span{display:block;height:10px;border-radius:5px;width:60%}.kh-cv-skel .kh-cv-t>span+span{width:85%}@keyframes khSkel{to{background-position-x:-200%}}.kh-new-err{color:var(--block-ink)}.kh-thread{flex:1 1 auto;overflow-y:auto;padding:1.1rem 1.1rem .6rem;display:flex;flex-direction:column;gap:2px;background:var(--bg-2)}.kh-row{display:flex;align-items:flex-end;gap:.5rem;max-width:78%}.kh-row.me{align-self:flex-end;flex-direction:row-reverse}.kh-row.first{margin-top:.7rem}.kh-col{display:flex;flex-direction:column;gap:2px;min-width:0}.kh-row.me .kh-col{align-items:flex-end}.kh-name{display:flex;align-items:center;gap:.4rem;font-size:.74rem;color:var(--muted);padding:0 .75rem .2rem;background:none;border:0;cursor:pointer;font-family:inherit}.kh-name b{color:hsl(var(--h) 75% 72%);font-weight:600}.khala-app[data-theme=light] .kh-name b{color:hsl(var(--h) 60% 35%)}.kh-name:hover b{text-decoration:underline}.kh-b{padding:.5rem .8rem;border-radius:18px;font-size:.92rem;line-height:1.4;background:var(--surface-3);color:var(--fg);text-wrap:pretty;overflow-wrap:anywhere;position:relative}.kh-row:not(.me) .kh-b{border-top-left-radius:18px}.kh-row:not(.me).mid .kh-b,.kh-row:not(.me).last-of .kh-b{border-top-left-radius:6px}.kh-row:not(.me).first:not(.last-of) .kh-b,.kh-row:not(.me).mid .kh-b{border-bottom-left-radius:6px}.kh-row.me .kh-b{background:var(--hs, var(--accent));color:#fff}.kh-row.me.mid .kh-b,.kh-row.me.last-of .kh-b{border-top-right-radius:6px}.kh-row.me.first:not(.last-of) .kh-b,.kh-row.me.mid .kh-b{border-bottom-right-radius:6px}.kh-b code{font-family:JetBrains Mono,monospace;font-size:.82em;padding:1px 5px;border-radius:5px;background:#00000038}.kh-mention{font-weight:600;color:hsl(var(--mh) 75% 74%);cursor:pointer}.khala-app[data-theme=light] .kh-mention{color:hsl(var(--mh) 60% 34%)}.kh-row.me .kh-mention{color:#fff;text-decoration:underline;text-underline-offset:2px}.kh-mention:hover{text-decoration:underline}.kh-row.human .kh-b{background:var(--hb, hsl(330 42% 30%));color:#fff}.khala-app[data-theme=light] .kh-row.human .kh-b{background:var(--hb-l, hsl(330 62% 86%));color:var(--hk, #3a1026)}.kh-row.human .kh-b code{background:#0003}.kh-row.human .kh-mention{color:#fff;text-decoration:underline;text-underline-offset:2px}.khala-app[data-theme=light] .kh-row.human .kh-mention{color:var(--hk, #3a1026)}.kh-kind{display:inline-grid;place-items:center;flex:0 0 auto;width:13px;height:13px}.kh-kind svg{width:13px;height:13px}.kh-kind-human{color:var(--accent)}.kh-kind-agent{color:var(--accent-complement)}.kh-row.agent{--ob: hsl(var(--oh) 65% 48%);--ob-mix: 30%}.khala-app[data-theme=light] .kh-row.agent{--ob-mix: 28%}.kh-row.agent .kh-b{background:color-mix(in srgb,var(--ob) var(--ob-mix),var(--surface-3))}.kh-row.agent .kh-mention{color:inherit;text-decoration:underline;text-underline-offset:2px}.kh-mention.kh-hm{background:hsl(var(--mh) 60% 50% / .16);padding:0 4px;border-radius:5px}.kh-row.me .kh-mention.kh-hm,.kh-row.human .kh-mention.kh-hm{background:#ffffff2e;text-decoration:none}.kh-retry{align-self:center;color:var(--block)}.kh-row.failed .kh-b{opacity:.55}@media(max-width:760px){.kh-row{max-width:88%}.kh-thread{padding:.8rem .7rem .5rem}.kh-b{font-size:.95rem}}.kh-pre{margin:.35rem 0 0;padding:.55rem .7rem;border-radius:10px;background:#00000038;font:.82em/1.45 JetBrains Mono,monospace;overflow-x:auto;white-space:pre}.khala-app[data-theme=light] .kh-pre{background:#2a251a14}.kh-pre-lang{display:block;font-size:.68rem;color:var(--muted);margin-bottom:.25rem}.kh-rcpt{align-self:flex-end;font-size:.7rem;color:var(--faint);padding:.15rem .3rem 0}.kh-rcpt b{color:var(--muted);font-weight:600}.kh-rcpt.kh-fail{color:var(--block);font-weight:600}.kh-row.pending .kh-b{opacity:.7}.kh-row.pop{animation:khPop .22s ease-out}@keyframes khPop{0%{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:none}}.kh-day{align-self:center;font-size:.72rem;color:var(--faint);margin:.9rem 0 .6rem;font-weight:600}.kh-day b{color:var(--muted);font-weight:600}.kh-ev{align-self:center;display:flex;align-items:center;gap:.45rem;font-size:.76rem;color:var(--muted);margin:.7rem 0 .2rem;padding:.3rem .75rem;border-radius:999px;border:1px solid var(--line);background:var(--surface);cursor:pointer;font-family:inherit}.kh-ev i{width:7px;height:7px;border-radius:50%;background:var(--good)}.kh-ev:hover{border-color:var(--line-strong);color:var(--fg)}.kh-ev--static{cursor:default}.kh-ev--static i{background:var(--muted)}.kh-ev--static:hover{border-color:var(--line);color:var(--muted)}.kh-thread .channel-event-pill{align-self:center;margin:.7rem 0 .2rem}.kh-thread .channel-event-pill__link{display:flex;align-items:center;gap:.45rem;font-size:.76rem;color:var(--muted);padding:.3rem .75rem;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-family:inherit}.kh-thread a.channel-event-pill__link:hover{border-color:var(--line-strong);color:var(--fg)}.kh-thread .channel-event-pill__dot{background:var(--good)}.kh-empty{margin:auto;display:flex;flex-direction:column;align-items:center;gap:.7rem;color:var(--muted);font-size:.9rem}.timeline__list.kh-thread{flex:1 1 auto;list-style:none;margin:0;padding:1.1rem 1.1rem .6rem;gap:2px;max-height:none;min-height:0}@media(max-width:760px){.timeline__list.kh-thread{padding:.8rem .7rem .5rem}}.conversation-thread__body .timeline{height:100%;gap:0;min-height:0}.timeline__state{align-self:center;margin:1rem}.timeline__state[role=alert]>b{color:var(--fg)}.kh-channel-thread{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:auto}.kh-head{display:flex;align-items:center;gap:.8rem;padding:.85rem 1.1rem;border-bottom:1px solid var(--line);background:var(--surface)}.kh-stack{display:flex}.kh-stack .kh-av{width:30px;height:30px;margin-left:-8px;border:2px solid var(--surface)}.kh-stack .kh-av:first-child{margin-left:0}.kh-head-t{display:flex;flex-direction:column;align-items:flex-start;min-width:0;flex:1 1 auto;border:0;background:none;color:var(--fg);font:inherit;text-align:left;padding:.2rem .45rem;margin:-.2rem -.45rem;border-radius:10px;cursor:pointer}.kh-head-t:hover{background:var(--surface-2)}.kh-head-t>b{display:flex;align-items:center;gap:.3rem;max-width:100%;font-size:.98rem;letter-spacing:-.01em}.kh-head-t>b>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kh-chev{display:inline-grid;width:16px;height:16px;flex:0 0 auto;color:var(--muted);transition:transform .2s}.kh-chev svg{width:16px;height:16px}.roster-open .kh-chev{transform:rotate(180deg)}.kh-head-t>span{font-size:.78rem;color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kh-head-t .on{color:var(--good-ink)}.kh-hacts{display:flex;gap:2px;margin-left:auto;flex:0 0 auto}.kh-hacts:after{content:"";flex:0 0 34px}@media(pointer:coarse){.kh-hacts:after{flex-basis:44px}}@media(max-width:760px){.kh-head{padding:.65rem .75rem;gap:.55rem}.kh-stack .kh-av:nth-child(n+3){display:none}}.kh-id{font-family:JetBrains Mono,monospace;font-size:.68rem;padding:1px 6px;border-radius:999px;background:hsl(var(--h) 60% 50% / .14);color:hsl(var(--h) 70% 72%);border:1px solid hsl(var(--h) 60% 50% / .3)}.khala-app[data-theme=light] .kh-id{color:hsl(var(--h) 60% 32%)}.kh-rai b .kh-id,.kh-d-hero b .kh-id,.kh-d-agent b .kh-id{margin-left:.3rem;font-weight:400}.kh-roster{position:absolute;left:0;right:0;top:var(--kh-head-h, 60px);z-index:4;display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s ease;background:var(--surface);border-bottom:1px solid transparent}.kh-roster.is-open{box-shadow:0 18px 40px -18px #0000008c}.kh-roster.is-open{grid-template-rows:1fr;border-bottom-color:var(--line)}.kh-roster-in{overflow:hidden;min-height:0}.kh-roster.is-open .kh-roster-in{overflow-y:scroll;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--line-strong) transparent;max-height:var(--kh-roster-max, 320px);padding:.5rem .7rem .8rem;display:flex;flex-direction:column;gap:.35rem}.kh-rg{display:flex;flex-direction:column}.kh-rh,.kh-rai{display:flex;align-items:center;gap:.6rem;width:100%;padding:.45rem .5rem;border:0;border-radius:12px;background:none;color:var(--fg);font:inherit;text-align:left;cursor:pointer;min-height:44px}.kh-rh:hover,.kh-rai:hover{background:var(--surface-2)}.kh-rh>span:nth-child(2),.kh-rai>span:nth-child(2){flex:1;min-width:0;display:flex;flex-direction:column}.kh-rh b,.kh-rai b{font-size:.88rem;font-weight:600}.kh-rh em,.kh-rai em{font-style:normal;font-size:.76rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kh-rh>i{font-style:normal;font-size:.72rem;color:var(--faint);flex:0 0 auto}.kh-ra{margin-left:1.45rem;padding-left:.8rem;border-left:2px solid var(--line);display:flex;flex-direction:column}.kh-rai .kh-av{width:28px;height:28px}.kh-rai .kh-av img{width:14px;height:14px}.kh-rrow{display:flex;align-items:center;gap:.3rem;border-radius:12px}.kh-rrow:hover{background:var(--surface-2)}.kh-rrow>.kh-rh,.kh-rrow>.kh-rai{flex:1;min-width:0;background:none!important}.kh-racts{display:flex;align-items:center;gap:4px;flex:0 0 auto;padding-right:.3rem}.kh-mode-ro{position:relative;width:26px;height:26px;display:grid;place-items:center;color:var(--muted);border-radius:7px;flex:0 0 auto}.kh-mode-ro svg{width:14px;height:14px}.kh-mode-btn{display:none;color:var(--accent-ink)}.kh-roster-in.more{-webkit-mask-image:linear-gradient(#000 calc(100% - 36px),transparent);mask-image:linear-gradient(#000 calc(100% - 36px),transparent)}.kh-roster-in::-webkit-scrollbar{width:6px}.kh-roster-in::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:3px}.kh-rlbl{display:flex;align-items:center;gap:.4rem;padding:.3rem .5rem .15rem;font-size:.68rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700;color:var(--faint)}@container khm (max-width: 600px){.kh-rh>i{display:none}}@container khm (max-width: 520px){.kh-stack,.kh-seg.ic{display:none}.kh-mode-btn{display:grid}}@media(max-width:760px){.kh-ra{margin-left:1.1rem}}.kh-roster-status{padding:.3rem .5rem;font-size:.8rem;color:var(--muted)}.kh-mode-status{margin:0;padding:0 .5rem .3rem calc(1.1rem + 28px);font-size:.76rem}.kh-to{display:block;padding:.5rem .9rem 0;background:var(--surface);border-top:1px solid var(--line)}.kh-to+.kh-comp{border-top:0;padding-top:.45rem}.kh-to-flat{display:flex;gap:.35rem;flex-wrap:wrap;align-items:center}.kh-to-grid{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.4rem .5rem;align-items:start;max-height:min(38vh,180px);overflow-y:auto}.kh-to-h{display:flex}.kh-to-ags{display:flex;flex-wrap:wrap;gap:.35rem}.kh-to-foot{display:flex;align-items:center;justify-content:space-between;margin-top:.45rem;font-size:.72rem;color:var(--faint)}.kh-to.is-open{padding-top:.7rem;animation:khUp .2s ease-out}@keyframes khUp{0%{opacity:.4;transform:translateY(8px)}to{opacity:1;transform:none}}.kh-to-tog{display:inline-flex;align-items:center;gap:.25rem;font:600 .72rem JetBrains Mono,monospace;padding:3px 8px;border-radius:999px;border:1px solid var(--line-strong);background:var(--surface-3);color:var(--fg);cursor:pointer}.kh-to-tog svg{width:12px;height:12px;transition:transform .2s}.kh-to.is-open .kh-to-tog svg{transform:rotate(180deg)}.kh-chip-me{cursor:default;opacity:.85}.kh-chip{font-family:JetBrains Mono,monospace;font-size:.72rem;padding:3px 9px;border-radius:999px;border:1px solid var(--pill-bd);background:var(--pill-bg);color:var(--muted);cursor:pointer}.kh-chip:hover{color:var(--fg);border-color:var(--line-strong)}.kh-chip-a{display:inline-flex;align-items:center;gap:.35rem;padding:2px 3px 2px 7px;color:var(--fg);border-color:hsl(var(--oh) 60% 55% / .45);background:hsl(var(--oh) 60% 50% / .08)}.kh-chip-a img{width:12px;height:12px;flex:0 0 auto}.kh-chip.kh-chip-a{color:hsl(var(--oh) 70% 72%)}.khala-app[data-theme=light] .kh-chip.kh-chip-a{color:hsl(var(--oh) 60% 36%)}.kh-chip-a i{font-style:normal;font:700 8px/16px JetBrains Mono,monospace;min-width:16px;height:16px;padding:0 3px;box-sizing:border-box;text-align:center;border-radius:999px;background:var(--hc, hsl(var(--oh) 65% 29%));color:#fff}.kh-chip-h{display:inline-flex;align-items:center;gap:.35rem;padding:2px 9px 2px 3px}.kh-chip-h i{font-style:normal;font:700 8px/16px JetBrains Mono,monospace;min-width:16px;height:16px;padding:0 3px;box-sizing:border-box;text-align:center;border-radius:999px;background:var(--hc, hsl(var(--oh) 65% 29%));color:#fff}.kh-chip-h{color:hsl(var(--oh) 70% 72%);border-color:hsl(var(--oh) 60% 55% / .45);background:hsl(var(--oh) 60% 50% / .1)}.khala-app[data-theme=light] .kh-chip-h{color:hsl(var(--oh) 60% 36%)}.kh-comp{display:flex;align-items:flex-end;gap:.55rem;padding:.7rem .9rem .85rem;border-top:1px solid var(--line);background:var(--surface)}.kh-input{flex:1 1 auto;min-height:38px;max-height:140px;resize:none;border-radius:19px;border:1px solid var(--line-strong);background:var(--bg-2);color:var(--fg);padding:.5rem .95rem;font:inherit;font-size:.92rem;line-height:1.4;outline:none}.kh-input:focus{border-color:var(--accent-line);box-shadow:0 0 0 3px var(--accent-soft)}.kh-send{flex:0 0 auto;width:38px;height:38px;border-radius:50%;border:0;background:var(--accent);color:#fff;display:grid;place-items:center;cursor:pointer;transition:opacity .15s,transform .15s}.kh-send:disabled{opacity:.35;cursor:default}.kh-send:not(:disabled):active{transform:scale(.92)}.kh-send svg{width:18px;height:18px}@media(max-width:760px){.kh-to{padding:.45rem .6rem 0}.kh-to-flat{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}.kh-to-flat>*{flex:0 0 auto}.kh-chip,.kh-to-tog{min-height:30px}.kh-to-grid{grid-template-columns:minmax(0,1fr);gap:.25rem}.kh-to-ags{padding-left:1.4rem;margin-bottom:.35rem}.kh-input{font-size:16px;min-height:40px}.kh-send{width:40px;height:40px}.kh-comp{padding:.55rem .6rem .65rem}}.kh-comp{position:relative}.kh-mpop{position:absolute;left:.9rem;bottom:calc(100% + 6px);z-index:25;width:min(320px,calc(100% - 1.8rem));max-height:min(40vh,296px);overflow-y:auto;box-sizing:border-box;margin:0;padding:.3rem;list-style:none;border-radius:14px;background:var(--surface);border:1px solid var(--line-strong);box-shadow:var(--shadow-lg);animation:khPopIn .14s ease-out}.kh-mpop-opt{display:flex;align-items:center;gap:.55rem;padding:.45rem .6rem;border-radius:9px;min-height:36px;box-sizing:border-box;cursor:pointer;color:var(--fg);font-size:.84rem}.kh-mpop-opt[aria-selected=true],.kh-mpop-opt:hover{background:var(--surface-2)}.kh-mpop-opt b{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}.kh-mpop-opt em{margin-left:auto;padding-left:.8rem;flex:0 0 auto;font-style:normal;font-size:.72rem;color:var(--faint);white-space:nowrap}.kh-mpop-opt img{width:20px;height:20px;flex:0 0 auto}.kh-mpop-opt i.kh-mpop-ag{display:grid;place-items:center;padding:0}.kh-mpop-opt i.kh-mpop-ag img{width:12px;height:12px;filter:brightness(0) invert(1)}.kh-mpop-opt i{flex:0 0 auto;font:700 9px/20px JetBrains Mono,monospace;min-width:20px;height:20px;padding:0 3px;box-sizing:border-box;text-align:center;border-radius:999px;background:var(--hc, hsl(var(--oh) 65% 29%));color:#fff}@media(pointer:coarse){.kh-mpop-opt{min-height:44px}}@media(max-width:760px){.kh-mpop{left:.6rem;right:.6rem;width:auto}}.section-card{background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow-sm)}.kh-card{padding:0!important;overflow:hidden;display:grid;grid-template-columns:300px minmax(0,1fr) 0px;height:calc(100vh - 190px);min-height:540px;transition:grid-template-columns .25s ease}.kh-card.has-detail{grid-template-columns:300px minmax(0,1fr) 320px}.kh-list{display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--line);background:var(--surface)}.kh-back{display:none;width:34px;height:34px;margin-left:-.4rem;border:0;border-radius:50%;background:none;color:var(--accent-ink);cursor:pointer;place-items:center}.kh-back svg{width:20px;height:20px}.kh-back:hover{background:var(--surface-2)}.kh-main{display:flex;flex-direction:column;min-width:0;min-height:0;position:relative}.kh-detail{border-left:1px solid var(--line);background:var(--surface);overflow-y:auto;min-width:0}.kh-state{flex:1;display:grid;place-items:center;background:var(--bg-2);padding:1.5rem}.kh-state[hidden]{display:none}.kh-state-c{display:flex;flex-direction:column;align-items:center;gap:.75rem;padding:1.4rem 1.8rem;border-radius:16px;background:var(--surface);border:1px solid var(--line);text-align:center}.kh-state-c>svg{width:24px;height:24px;color:var(--faint)}.kh-state-c b{font-size:.98rem}.kh-spin{width:22px;height:22px;box-sizing:border-box;border-radius:50%;border:2.5px solid var(--line-strong);border-top-color:var(--accent);animation:khSpin .8s linear infinite}@keyframes khSpin{to{transform:rotate(360deg)}}.kh-loading{flex:1 1 auto;display:grid;place-items:center;min-height:0}.kh-loading--overlay{position:absolute;inset:0;z-index:1;pointer-events:none}.kh-state>.kh-state{padding:0}@media(max-width:1100px){.kh-card,.kh-card.has-detail{grid-template-columns:260px minmax(0,1fr) 0px}.kh-card{position:relative}.kh-detail{position:absolute;top:0;right:0;bottom:0;width:320px;transform:translate(100%);transition:transform .25s ease;z-index:5;box-shadow:var(--shadow-lg)}.kh-card.has-detail .kh-detail{transform:none}}@media(max-width:900px){.kh-card,.kh-card.has-detail{grid-template-columns:minmax(0,1fr)}.kh-card:not(.in-thread) .kh-main{display:none}.kh-card.in-thread .kh-list{display:none}.kh-back{display:grid}.kh-list{border-right:0}}@media(max-width:760px){.kh-card,.kh-card.has-detail{grid-template-columns:minmax(0,1fr);position:relative;height:calc(100vh - 210px)}.kh-detail{position:absolute;inset:0;transform:translate(100%);transition:transform .25s ease;z-index:5;border-left:0}.kh-card.has-detail .kh-detail{transform:none}.kh-card,.kh-card.has-detail{height:calc(100dvh - 190px);min-height:420px;border-radius:var(--radius)}}.khala-app{height:100vh;height:100dvh}.khala-app .kh-card,.khala-app .kh-card.has-detail{height:100%;min-height:0;border:0;border-radius:0;box-shadow:none}@media(max-width:760px){.khala-app .kh-card,.khala-app .kh-card.has-detail{height:100%;min-height:0;border-radius:0}.khala-app .kh-comp{padding-bottom:calc(.65rem + env(safe-area-inset-bottom,0px))}.khala-app .kh-detail{width:auto}}.khala-app .kh-card:not(.has-detail) .kh-detail{visibility:hidden;transition:transform .25s ease,visibility 0s linear .25s}.khala-app .kh-card.has-detail .kh-detail{visibility:visible}.khala-app .kh-card.kh-solo{grid-template-columns:minmax(0,1fr) 0px}.khala-app .kh-card.kh-solo .kh-main{display:flex}.khala-app .kh-solo .kh-brand{border-bottom:1px solid var(--line);padding-bottom:.9rem;background:var(--surface)}@media(max-width:900px){.khala-pending .kh-card{grid-template-rows:auto minmax(0,1fr)}.khala-pending .kh-card .kh-main{display:flex;border-top:1px solid var(--line)}}.kh-brand{display:flex;align-items:center;gap:.55rem;padding:.9rem .8rem .35rem 1rem}.kh-brand .brand-logo{height:24px;width:auto;display:block}.kh-brand .wm{font-family:Bungee,sans-serif;font-size:1.05rem;line-height:1;letter-spacing:.01em;color:var(--fg);text-transform:uppercase;text-decoration:none}.kh-brand-actions{margin-left:auto;min-width:0;display:flex;align-items:center;gap:.4rem}.tool-btn{display:inline-flex;align-items:center;gap:.45rem;border:1px solid var(--pill-bd);background:var(--pill-bg);color:var(--muted);border-radius:999px;padding:.44rem .82rem;font-family:JetBrains Mono,monospace;font-size:.76rem;letter-spacing:.02em;font-weight:500;transition:color .2s ease,border-color .2s ease,background .2s ease}.tool-btn:hover{color:var(--fg);border-color:var(--line-strong)}.tool-btn svg{width:15px;height:15px}.tool-btn.is-on{color:var(--fg);border-color:var(--accent-line);background:var(--accent-soft)}.tool-btn.icon-only{gap:0;padding:0;width:2.05rem;height:2.05rem;justify-content:center;border-radius:50%;aspect-ratio:1;flex:none}.tool-btn:disabled{cursor:wait;opacity:.6}.toggle-icon{display:inline-flex;align-items:center;justify-content:center}.toggle-icon svg{display:block}.toggle-icon .moon,.khala-app[data-theme=light] .toggle-icon .sun{display:none}.khala-app[data-theme=light] .toggle-icon .moon{display:inline}.khala-app .status-badge{display:inline-flex;align-items:center;gap:.42rem;min-height:1.9rem;padding:.3rem .72rem;border-radius:999px;border:1px solid var(--pill-bd);background:var(--pill-bg);color:var(--muted);font-family:JetBrains Mono,monospace;font-size:.72rem;font-weight:600;letter-spacing:.03em}.status-badge-dot{width:.5rem;height:.5rem;border-radius:999px;background:currentColor}.khala-app .status-badge-live{background:var(--good-soft);border-color:var(--good-line);color:var(--good-ink)}.status-badge-live .status-badge-dot{background:var(--good);box-shadow:0 0 8px var(--good);animation:pulse 2s ease-in-out infinite}.status-badge-offline{display:none}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}.kh-brand-status{min-width:0;font-size:.72rem;color:var(--muted);text-align:right}.kh-brand-status[role=alert]{color:var(--block-ink)}.kh-av{flex:0 0 auto;width:32px;height:32px;border-radius:50%;display:grid;place-items:center;background:hsl(var(--h) 45% 22%);border:1px solid hsl(var(--h) 60% 50% / .5);cursor:pointer;padding:0}.khala-app[data-theme=light] .kh-av{background:hsl(var(--h) 55% 88%)}.kh-av img{width:17px;height:17px}.kh-av.ghost{visibility:hidden;cursor:default}.kh-av{position:relative}.kh-own{position:absolute;right:-4px;bottom:-4px;min-width:16px;height:16px;padding:0 3px;border-radius:999px;font:700 8px/16px JetBrains Mono,monospace;letter-spacing:-.02em;color:#fff;background:var(--hc, hsl(var(--oh) 65% 29%));border:2px solid var(--bg-2);box-sizing:content-box}.kh-stack .kh-own,.kh-d-hero .kh-own{display:none}.kh-aav{background:var(--hc, hsl(var(--oh) 65% 29%))!important;border-color:transparent}.kh-aav img{filter:brightness(0) invert(1)}.khala-app .kh-av.kh-aav .kh-ini{color:#fff}.kh-hav{background:var(--hc, hsl(var(--oh) 65% 29%))!important;border-color:transparent;color:#fff;font:700 .72rem/1 Space Grotesk,sans-serif;letter-spacing:.02em}.kh-d-hero .kh-hav{font-size:1.3rem}[data-kh-tier="1"].kh-hav{box-shadow:0 0 0 2px var(--bg-2),0 0 0 3.5px var(--hc)}[data-kh-tier="2"].kh-hav{outline:1.5px dashed var(--hc);outline-offset:2px}.kh-more{font:700 .66rem/1 JetBrains Mono,monospace;color:var(--muted);background:var(--surface-3)!important;border-color:var(--line)!important;cursor:default}.kh-gen{background:var(--surface-3)!important;border-color:var(--line)!important;color:var(--faint);font:700 .9rem/1 JetBrains Mono,monospace}.kh-st{position:absolute;left:-2px;top:-2px;width:8px;height:8px;border-radius:50%;border:2px solid var(--surface);background:var(--good)}.kh-st.off{background:var(--faint)}.kh-st.err{background:var(--block)}.kh-ini{font:700 .72rem/1 Space Grotesk,sans-serif;letter-spacing:.02em;color:hsl(var(--h) 75% 72%)}.khala-app[data-theme=light] .kh-ini{color:hsl(var(--h) 60% 35%)}.kh-d-hero .kh-ini{font-size:1.3rem}@media(prefers-reduced-motion:reduce){.khala-app *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.khala-app :is(button,a,[role=button],input[type=search]):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.khala-app .kh-cv.is-active:focus-visible{outline-color:#fff;outline-offset:-3px}.khala-app .kh-search:focus-within{box-shadow:0 0 0 3px var(--accent-soft)}.khala-app :is(.kh-input,.kh-txt):focus-visible{outline:none}.kh-list>.conversation-list{flex:1;min-height:0;border-right:0;background:none}.kh-main>:not(.kh-toast,.kh-brand){flex:1 1 auto;min-height:0;overflow:auto}.kh-main>.khala-page-frame,.kh-main>.khala-inactive-device{width:100%;padding:clamp(1rem,3vw,2rem)}.kh-main>.channel-page,.kh-main>.channel-page>.khala-page-frame,.kh-main>.channel-page .khala-page-frame__body{display:flex;flex-direction:column;min-height:0;max-width:none;margin:0}.kh-main>.channel-page>.khala-page-frame,.kh-main>.channel-page .khala-page-frame__body{flex:1 1 auto}.kh-main>.channel-page .conversation-layout{flex:1 1 auto;height:auto;min-height:0;border:0;border-radius:0}.kh-main>.kh-channel{display:flex;flex-direction:column;overflow:hidden}.kh-state>.khala-page-frame{width:min(36rem,100%)}.kh-main>.kh-state{place-items:safe center}.kh-fin{position:absolute;inset:0;z-index:40;display:grid;place-items:center;background:var(--bg-2);padding:1.2rem}.kh-fin[hidden]{display:none}.kh-fin-c{width:min(340px,100%);box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:.85rem;text-align:center;padding:1.8rem 1.4rem;border-radius:20px;background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow-lg)}.kh-fin-eb{font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--faint)}.kh-fin-n{font-size:1.45rem;font-weight:700;letter-spacing:-.02em;overflow-wrap:anywhere}.kh-fin .kh-btn{width:100%;height:44px;margin-top:.3rem}h1.kh-fin-n{margin:0}.kh-fin-p{margin:0;font-size:.82rem;color:var(--muted)}.kh-fin-p b{color:var(--fg);font-weight:600}.kh-fin-ok{display:inline-flex;align-items:center;gap:.35rem;font-size:.84rem;font-weight:600;color:var(--good-ink)}.kh-fin-ok svg{width:15px;height:15px}.kh-fin-err{color:var(--block-ink)}.kh-fin a.kh-btn{display:grid;place-items:center;text-decoration:none}.kh-fin--page{position:fixed;inset:0}.khala-app>.kh-brand{position:fixed;top:0;left:0;z-index:41}.kh-fin-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kh-mchip{display:inline-flex;align-items:center;gap:.3rem;padding:2px 8px 2px 6px;border-radius:999px;background:var(--surface-3);border:1px solid var(--line);font:.72rem JetBrains Mono,monospace;color:var(--fg)}.kh-mchip img{width:12px;height:12px}.conversation-layout{display:grid;grid-template-columns:300px minmax(0,1fr);height:min(760px,calc(100dvh - 190px));min-height:540px;border:1px solid var(--khala-line);border-radius:16px;overflow:hidden;background:var(--khala-fill-raised);color:var(--khala-ink)}.conversation-layout--detail{grid-template-columns:300px minmax(0,1fr) 320px}.conversation-list{display:flex;flex-direction:column;min-width:0;min-height:0;border-right:1px solid var(--khala-line);background:var(--khala-fill-raised)}.conversation-list__head{display:flex;align-items:baseline;justify-content:space-between;padding:1rem 1rem .6rem}.conversation-list__head strong{font-size:1.05rem;letter-spacing:-.02em}.conversation-list__head span{font-size:.76rem;color:var(--khala-ink-muted)}.conversation-list__head-actions{display:flex;align-items:center;gap:.45rem}.conversation-list__search{display:flex;align-items:center;gap:.45rem;margin:0 .8rem .6rem;padding:0 .7rem;height:34px;border-radius:10px;background:var(--khala-fill-control);color:var(--khala-ink-muted)}.conversation-list__search svg{width:15px;height:15px;flex:none}.conversation-list__search input{min-width:0;width:100%;border:0;background:none;color:inherit;font:inherit;font-size:.88rem;outline:none}.conversation-list__items{overflow:auto;min-height:0;padding:0 .5rem .6rem}.conversation-list__items>p{text-align:center;font-size:.84rem;color:var(--khala-ink-muted);padding:1.2rem}.conversation-list__item{display:grid;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:.65rem;width:100%;padding:.6rem .55rem;border:0;border-radius:12px;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}.conversation-list__item:hover{background:var(--khala-fill-control)}.conversation-list__item.is-active{background:var(--khala-accent);color:#fff}.conversation-list__item.is-active .conversation-list__preview,.conversation-list__item.is-active time{color:#fffc}.conversation-list__avatar{display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:var(--khala-fill-control);border:1px solid var(--khala-line);font-weight:700}.conversation-list__copy{display:flex;flex-direction:column;gap:2px;min-width:0}.conversation-list__top{display:flex;align-items:baseline;gap:.5rem}.conversation-list__top strong{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.9rem}.conversation-list__top time{flex:none;font-size:.72rem;color:var(--khala-ink-muted)}.conversation-list__preview{overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:.8rem;line-height:1.35;color:var(--khala-ink-muted)}.conversation-list__unread{background:var(--khala-accent);color:#fff;border-radius:999px;padding:2px 6px;font-size:.7rem}.conversation-thread{display:flex;flex-direction:column;min-height:0;min-width:0}.conversation-thread--empty{align-items:center;justify-content:center;color:var(--khala-ink-muted)}.conversation-thread__head{display:flex;align-items:center;gap:.8rem;padding:.85rem 1.1rem;border-bottom:1px solid var(--khala-line);font-size:.98rem}.conversation-thread__back{display:none;border:0;background:none;color:var(--khala-accent);font-size:1.5rem;cursor:pointer}.conversation-thread__body{min-height:0;overflow:auto;flex:1;background:var(--khala-fill)}.conversation-detail{min-width:0;overflow:auto;border-left:1px solid var(--khala-line);padding:1.1rem}.conversation-detail>button{float:right;border:1px solid var(--khala-line);border-radius:50%;background:none;color:inherit;cursor:pointer}@media(max-width:1100px){.conversation-layout,.conversation-layout--detail{grid-template-columns:260px minmax(0,1fr)}.conversation-layout{position:relative}.conversation-detail{position:absolute;right:0;top:0;bottom:0;width:320px;background:var(--khala-fill-raised);box-shadow:0 8px 30px #0006}}@media(max-width:900px){.conversation-layout,.conversation-layout--detail{grid-template-columns:minmax(0,1fr)}.conversation-layout:not(.conversation-layout--thread) .conversation-thread{display:none}.conversation-layout--thread .conversation-list{display:none}.conversation-thread__back{display:block}.conversation-list{border-right:0}}@media(max-width:760px){.conversation-layout{height:calc(100dvh - 210px);min-height:360px}.conversation-detail{inset:0;width:auto}}.conversation-thread__actions{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;padding:.5rem 1.1rem;color:var(--khala-ink-muted);font-size:.78rem}.conversation-thread__actions button{border:1px solid var(--khala-line);border-radius:999px;background:var(--khala-fill-control);color:var(--khala-ink);padding:.3rem .7rem;cursor:pointer}.conversation-message{display:flex;align-items:flex-end;gap:.55rem;max-width:min(82%,38rem);min-width:0;list-style:none}.conversation-message--mine{align-self:flex-end;flex-direction:row-reverse}.conversation-message__avatar{display:grid;place-items:center;flex:none;width:28px;height:28px;border-radius:50%;background:var(--khala-fill-control);border:1px solid var(--khala-line);color:var(--khala-ink);font-size:.72rem;font-weight:700}.conversation-message--mine .conversation-message__avatar{border-color:var(--khala-accent);color:var(--khala-accent)}.conversation-message--grouped .conversation-message__avatar{visibility:hidden}.conversation-message__bubble{min-width:0;padding:.45rem .55rem;border:1px solid var(--khala-line);border-left:3px solid var(--khala-ink-muted);border-radius:6px;background:var(--khala-fill-raised);color:var(--khala-ink)}.conversation-message--mine .conversation-message__bubble{border-left:1px solid var(--khala-line);border-right:3px solid var(--khala-accent);background:color-mix(in srgb,var(--khala-fill-raised) 90%,var(--khala-accent))}.conversation-message__meta{display:flex;align-items:baseline;flex-wrap:wrap;gap:.35rem;margin-bottom:.2rem;color:var(--khala-ink-muted);font-size:.7rem}.conversation-message__meta strong{color:var(--khala-ink)}.conversation-message__kind{font-weight:600;text-transform:uppercase;letter-spacing:.03em}.conversation-message__meta time{margin-left:auto;font-size:.68rem}.conversation-message--grouped .conversation-message__meta strong{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.conversation-message__content{font-size:.82rem;line-height:1.4;white-space:pre-wrap;overflow-wrap:anywhere}.conversation-message__content p{margin:0}.fixture-messages{display:flex;flex:1;flex-direction:column;gap:.5rem;list-style:none;margin:0;padding:1.1rem;overflow:auto}.conversation-system-event{align-self:center;max-width:min(100%,36rem);list-style:none;text-align:center;color:var(--khala-ink-muted);font-size:.78rem;line-height:1.4;padding:.25rem .65rem}.conversation-system-event__text,.conversation-system-event__actor{display:block}.conversation-system-event__actor{font-size:.68rem;opacity:.8}.conversation-layout .sr-only,.kh-comp .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.conversation-thread__body{display:flex;flex-direction:column}.conversation-thread__head h2{margin:0;font:inherit;font-weight:700}.conversation-layout--no-list{grid-template-columns:minmax(0,1fr)}.conversation-layout--no-list.conversation-layout--detail{grid-template-columns:minmax(0,1fr) 320px}.conversation-thread__actions{justify-content:flex-end;gap:.5rem;padding:.45rem .85rem}.conversation-thread__actions>span{margin-right:auto}.conversation-thread__actions .aiur-shell__icon-button{padding:0;border-radius:50%;width:2.05rem;height:2.05rem}@media(max-width:900px){.conversation-layout--no-list .conversation-thread{display:flex}}@media(max-width:1100px){.conversation-layout--no-list.conversation-layout--detail{grid-template-columns:minmax(0,1fr)}}.conversation-layout{height:100%;min-height:0;border:0;border-radius:0;grid-template-columns:260px minmax(0,1fr)}.conversation-layout--detail{grid-template-columns:260px minmax(0,1fr) 320px}.conversation-list__head{padding:.9rem .85rem .65rem}.conversation-list__search{margin:0 .6rem .5rem;height:36px}.conversation-list__items{padding:0 .35rem .5rem}.conversation-list__item{grid-template-columns:38px minmax(0,1fr) auto;gap:.55rem;padding:.55rem .5rem;border-radius:10px;min-height:62px}.conversation-list__avatar{width:36px;height:36px;background:hsl(var(--avatar-hue) 53% 33%);border-color:hsl(var(--avatar-hue) 55% 42%);color:#fff;font-size:.83rem}.conversation-list__preview{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.76rem}.conversation-list__top strong{font-size:.84rem}.conversation-list__unread{min-width:7px;height:7px;padding:0;overflow:hidden;text-indent:-999px}.conversation-thread__head{min-height:66px;box-sizing:border-box;padding:.65rem 1rem;gap:.75rem;background:var(--khala-fill-raised)}.conversation-thread__identity{min-width:0;flex:1;display:grid;gap:.15rem}.conversation-thread__identity h2{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.94rem}.conversation-thread__header-actions{display:flex;align-items:center;gap:.4rem;flex:none}.conversation-message{align-items:flex-start;max-width:min(86%,42rem);gap:.45rem}.conversation-message__avatar{width:30px;height:30px;background:hsl(var(--avatar-hue) 53% 33%);border-color:hsl(var(--avatar-hue) 55% 42%);color:#fff}.conversation-message--mine .conversation-message__avatar{color:#fff;background:var(--khala-accent);border-color:var(--khala-accent)}.conversation-message__bubble{border:0;border-radius:13px;padding:.5rem .7rem;background:var(--khala-fill-control)}.conversation-message--mine .conversation-message__bubble{border:0;background:color-mix(in srgb,var(--khala-fill-control) 80%,var(--khala-accent))}.conversation-message__meta{margin-bottom:.25rem;font-size:.72rem;gap:.4rem}.conversation-message__meta time{color:var(--khala-ink-muted)}.conversation-message__content{font-size:.88rem;line-height:1.4}@media(max-width:1100px){.conversation-layout,.conversation-layout--detail{grid-template-columns:240px minmax(0,1fr)}}@media(max-width:900px){.conversation-layout,.conversation-layout--detail{grid-template-columns:minmax(0,1fr)}}@media(max-width:760px){.conversation-layout{height:100%;min-height:0}.conversation-message{max-width:calc(100% - .5rem)}.conversation-thread__head{padding:.55rem .7rem}.conversation-thread__header-actions{gap:.25rem}}.conversation-layout.conversation-layout--no-list{grid-template-columns:minmax(0,1fr)}.conversation-layout.conversation-layout--no-list.conversation-layout--detail{grid-template-columns:minmax(0,1fr) 320px}@media(max-width:1100px){.conversation-layout.conversation-layout--no-list.conversation-layout--detail{grid-template-columns:minmax(0,1fr)}}.kh-d-in{padding:1.1rem;display:flex;flex-direction:column;gap:1rem;width:320px;box-sizing:border-box}.kh-d-top{display:flex;align-items:flex-start;justify-content:space-between}.kh-d-x{width:30px;height:30px;border-radius:50%;border:1px solid var(--line);background:var(--surface-2);color:var(--muted);cursor:pointer;font-size:1rem;line-height:1}.kh-d-hero{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.45rem}.kh-d-hero .kh-av{width:64px;height:64px;cursor:default}.kh-d-hero .kh-av img{width:32px;height:32px}.kh-d-hero b{font-size:1.05rem}.kh-d-hero span{font-size:.8rem}.kh-d-hero>span:where(:not(.kh-av)){color:var(--muted)}.kh-d-hero .kh-email{max-width:100%;color:var(--fg);overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.kh-d-sec{display:flex;flex-direction:column;gap:.4rem;padding:.85rem;border-radius:14px;background:var(--surface-2);border:1px solid var(--hairline)}.kh-d-lbl{font-size:.68rem;text-transform:uppercase;letter-spacing:.08em;color:var(--faint);font-weight:600}.kh-d-sec p{margin:0;font-size:.88rem;line-height:1.45}.kh-d-kv{display:grid;grid-template-columns:auto 1fr;gap:.35rem .8rem;font-size:.82rem}.kh-d-kv dt{color:var(--muted)}.kh-d-kv dd{margin:0;text-align:right;font-family:JetBrains Mono,monospace;font-size:.78rem}.kh-d-act{display:flex;gap:.5rem}.kh-d-act button{flex:1;padding:.55rem;border-radius:12px;border:1px solid var(--line-strong);background:var(--surface-3);color:var(--fg);font:inherit;font-size:.84rem;font-weight:600;cursor:pointer}.kh-d-act button.pri{background:var(--accent);border-color:var(--accent);color:#fff}.kh-d-log{display:flex;flex-direction:column;gap:.45rem;font-size:.82rem;color:var(--muted)}.kh-d-log div{display:flex;gap:.5rem}.kh-d-log time{font-family:JetBrains Mono,monospace;font-size:.72rem;color:var(--faint);flex:0 0 auto;padding-top:1px}.kh-d-owner{white-space:nowrap;max-width:100%;display:inline-flex;align-items:center;gap:.4rem;margin-top:.2rem;padding:3px 10px 3px 3px;border-radius:999px;border:1px solid hsl(var(--oh) 60% 55% / .4);background:hsl(var(--oh) 60% 50% / .1);color:var(--fg);font:inherit;font-size:.78rem;cursor:pointer}.kh-d-owner>span{min-width:0;overflow:hidden;text-overflow:ellipsis}.kh-d-owner b{font-weight:600}.kh-d-owner i{flex:0 0 auto;width:20px;height:20px;border-radius:50%;display:grid;place-items:center;background:var(--hc, hsl(var(--oh) 65% 29%));color:#fff;font:700 8px/1 JetBrains Mono,monospace;font-style:normal}.kh-d-agents{display:flex;flex-direction:column;gap:.5rem}.kh-d-agent{display:flex;align-items:center;gap:.6rem;padding:.4rem;border-radius:12px;border:1px solid transparent;background:none;color:var(--fg);font:inherit;text-align:left;cursor:pointer}.kh-d-agent:hover{background:var(--surface-3)}.kh-d-agent>span{flex:1;min-width:0;display:flex;flex-direction:column;font-size:.84rem}.kh-d-agent em{font-style:normal;color:var(--muted);font-size:.78rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.khala-app .kh-d-owner b{font-size:inherit}.khala-app .kh-d-owner span{font-size:inherit;color:inherit}.khala-app .kh-d-kv{margin:0}.khala-app .kh-d-agent>.kh-av{flex:0 0 auto;display:grid;font-size:inherit}@media(max-width:760px){.kh-d-in{width:auto;padding:1rem .9rem calc(1rem + env(safe-area-inset-bottom,0px))}.kh-d-x{width:36px;height:36px}}.kh-d-rename{display:flex;flex-direction:column;gap:.5rem}.kh-d-rename .kh-row2 .kh-btn{flex:0 0 auto}.kh-d-rename-err{margin:0;color:var(--block-ink);font-size:.78rem;overflow-wrap:anywhere}.kh-uname-page{overflow-y:auto}.kh-uname-card{width:min(400px,100%);box-sizing:border-box;display:flex;flex-direction:column;gap:.85rem;padding:1.6rem 1.4rem;border-radius:20px;background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow-lg)}.kh-uname-card h1{margin:0;font-size:1.35rem;font-weight:700;letter-spacing:-.02em;outline:none}.kh-uname-card>p{margin:0;font-size:.86rem;color:var(--muted)}@media(max-width:480px){.kh-uname-page{padding:1rem;place-items:start stretch}.kh-uname-card{width:100%;padding:1.2rem 1rem}}.kh-uname{display:flex;flex-direction:column;gap:.45rem}.kh-uname-field{position:relative;display:flex;align-items:center}.kh-uname-at{position:absolute;left:.7rem;color:var(--faint);font-size:.88rem;pointer-events:none}.kh-uname-field .kh-txt{padding-left:1.55rem}.kh-uname-hint,.kh-uname-err{margin:0;font-size:.76rem;color:var(--faint);overflow-wrap:anywhere}.kh-uname-err{color:var(--block-ink)}.kh-txt[aria-invalid=true]{border-color:var(--block-line)}.kh-txt[aria-invalid=true]:focus{border-color:var(--block);box-shadow:0 0 0 3px var(--block-soft)}.kh-uname-actions{display:flex;justify-content:flex-end;gap:.4rem;margin-top:.3rem}.kh-uname-page .kh-uname-actions .kh-btn.pri{flex:1;height:44px}.kh-dlg-scrim{position:absolute;inset:0;z-index:40;display:grid;place-items:center;padding:16px;background:#0006}.kh-dlg{animation:khPopIn .14s ease-out;width:min(400px,100%);box-sizing:border-box;display:flex;flex-direction:column;gap:.75rem;padding:1.2rem 1.1rem;border-radius:14px;background:var(--surface);border:1px solid var(--line-strong);box-shadow:var(--shadow-lg)}.kh-dlg h2{margin:0;font-size:1.05rem;font-weight:700;letter-spacing:-.01em}@media(max-width:480px){.kh-dlg-scrim{place-items:start stretch}.kh-dlg{width:100%}}.kh-prof{position:relative;gap:1.25rem;padding:1.6rem 1.3rem 1.2rem}.kh-prof-h{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.kh-prof-ini{display:flex;align-items:flex-start;gap:1.1rem}.kh-prof-ini>.kh-prof-sec{flex:1;min-width:0;padding-top:.6rem}.kh-prof-av{flex:none;display:grid;place-items:center;width:72px;height:72px;margin:5px 0 5px 5px;border-radius:50%;color:#fff;font-size:1.5rem;font-weight:700;letter-spacing:.02em;box-shadow:0 0 0 4px var(--surface),0 0 0 5px var(--line);transition:background-color .18s ease}.kh-prof-av.is-default>span{opacity:.75}.kh-prof-ini-in{width:3.6rem;padding:0 .5rem;text-align:center;text-transform:uppercase;font-weight:600;letter-spacing:.06em}.kh-prof-ini-in::placeholder{color:var(--faint);opacity:1}.kh-prof-form{display:flex;flex-direction:column;gap:1.1rem}.kh-prof-sec{display:flex;flex-direction:column;gap:.45rem}.kh-prof-lbl{font-size:.72rem;font-weight:600;color:var(--muted)}.kh-prof .kh-uname-actions{margin-top:.2rem}.kh-swatches{display:grid;grid-template-columns:repeat(10,1fr);justify-items:center;gap:.3rem 0}.kh-swatch{display:grid;place-items:center;width:36px;height:36px;padding:0;border:0;border-radius:50%;background:none;cursor:pointer}.kh-swatch>span{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;color:#fff;transition:transform .12s ease}.kh-swatch:hover>span{transform:scale(1.08)}.kh-swatch[aria-checked=true]>span{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--fg)}.kh-swatch svg{width:16px;height:16px}.kh-swatch:focus-visible{outline:2px solid var(--accent);outline-offset:3px}@media(max-width:480px),(pointer:coarse){.kh-swatches{grid-template-columns:repeat(5,1fr);gap:.35rem 0}.kh-swatch{width:44px;height:44px}.kh-swatch>span{width:32px;height:32px}}@media(prefers-reduced-motion:reduce){.kh-prof-av,.kh-swatch>span{transition:none}}.channel-event-pill{align-self:center;list-style:none;max-width:100%}.channel-event-pill__link{display:inline-flex;align-items:center;gap:.3rem;padding:.25rem .6rem;border:1px solid var(--khala-line);border-radius:999px;color:var(--khala-ink-muted);font-size:.75rem;text-decoration:none;max-width:100%;box-sizing:border-box}.channel-event-pill__body{min-width:0;overflow-wrap:anywhere}.channel-event-pill__dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}.channel-event-pill__dot--success{background:var(--khala-status-positive)}.channel-event-pill__dot--failure{background:var(--khala-status-critical)}.channel-event-pill__dot--attention{background:var(--khala-status-caution)}.channel-event-pill__dot--pending{background:var(--khala-accent)}.channel-event-pill__dot--info{background:var(--khala-ink-muted)}@font-face{font-family:Space Grotesk;src:url(/assets/SpaceGrotesk-Variable-BWuzNAiS.woff2) format("woff2");font-style:normal;font-weight:300 700;font-display:block}@font-face{font-family:JetBrains Mono;src:url(/assets/JetBrainsMono-Variable-CZ7Klmjc.woff2) format("woff2");font-style:normal;font-weight:100 800;font-display:block}@font-face{font-family:Bungee;src:url(/assets/Bungee-Regular-BC4W3tCU.woff2) format("woff2");font-style:normal;font-weight:400;font-display:block}:root,[data-theme=dark]{--aiur-bg: #1a1b1e;--aiur-bg-soft: #161719;--aiur-fg: #edeef0;--aiur-muted: #8c8d93;--aiur-line: rgba(221, 226, 235, .14);--aiur-hairline: rgba(221, 226, 235, .1);--aiur-pill-border: rgba(221, 226, 235, .13);--aiur-pill-bg: rgba(221, 226, 235, .03);--aiur-accent: #2f86ff;--aiur-accent-strong: #0070f0;--aiur-on-accent: #ffffff;--aiur-accent-soft: rgba(47, 134, 255, .15);--aiur-font-body: "Aiur Space Grotesk", system-ui, sans-serif;--aiur-font-mono: "Aiur JetBrains Mono", monospace;--aiur-font-display: "Aiur Bungee", sans-serif;--aiur-topbar-link-size: 13px;--aiur-logo-size: clamp(120px, 18vw, 224px);--aiur-wordmark-size: clamp(40px, 8vw, 96px);--aiur-tagline-size: clamp(16px, 2.2vw, 22px);--aiur-theme-toggle-size: 42px;--aiur-copy-control-size: 28px;--aiur-sun-display: block;--aiur-moon-display: none;--aiur-toggle-rotation: none}[data-theme=light]{--aiur-bg: #e7d6b2;--aiur-bg-soft: #e2cfa6;--aiur-fg: #2a2520;--aiur-muted: #5f5645;--aiur-line: rgba(42, 37, 26, .17);--aiur-hairline: rgba(42, 37, 26, .12);--aiur-pill-border: rgba(42, 37, 26, .16);--aiur-pill-bg: rgba(42, 37, 26, .035);--aiur-accent: #1f57c4;--aiur-accent-strong: #1f57c4;--aiur-on-accent: #ffffff;--aiur-accent-soft: rgba(31, 87, 196, .11);--aiur-sun-display: none;--aiur-moon-display: block;--aiur-toggle-rotation: rotate(360deg)}.khala-app,.khala-content-root{--bg: #16171a;--bg-2: #1a1b1e;--surface: #1e2025;--surface-2: #23262c;--surface-3: #292d34;--fg: #edeef0;--muted: #969aa4;--faint: #676b74;--line: rgba(221, 226, 235, .12);--line-strong: rgba(221, 226, 235, .2);--hairline: rgba(221, 226, 235, .08);--pill-bd: rgba(221, 226, 235, .14);--pill-bg: rgba(221, 226, 235, .04);--accent: #2f86ff;--accent-ink: #8fbcff;--accent-soft: rgba(47, 134, 255, .15);--accent-line: rgba(47, 134, 255, .34);--accent-complement: #c97103;--attn: #e3b341;--attn-ink: #f1cf6f;--attn-soft: rgba(227, 179, 65, .15);--attn-line: rgba(227, 179, 65, .34);--block: #ff7b72;--block-ink: #ffa39c;--block-soft: rgba(255, 123, 114, .14);--block-line: rgba(255, 123, 114, .34);--good: #3fb950;--good-ink: #74d47f;--good-soft: rgba(63, 185, 80, .14);--good-line: rgba(63, 185, 80, .32);--super: #c69bff;--super-ink: #d8bcff;--super-soft: rgba(198, 155, 255, .15);--super-line: rgba(198, 155, 255, .34);--ack: #4fd6c4;--ack-soft: rgba(79, 214, 196, .14);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);--shadow-lg: 0 40px 90px -40px rgba(0, 0, 0, .7);--radius: 16px;--radius-lg: 24px;color-scheme:dark;--khala-font-body: "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;--khala-font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;--khala-content-measure: 75rem;--khala-panel-radius: 16px;--khala-dialog-radius: 24px;--khala-fill: var(--bg);--khala-fill-raised: var(--surface);--khala-fill-control: var(--surface-3);--khala-ink: var(--fg);--khala-ink-muted: var(--muted);--khala-line: var(--line);--khala-accent: var(--accent);--khala-status-positive: var(--good);--khala-status-caution: var(--attn);--khala-status-critical: var(--block);color:var(--fg);background:var(--bg);font-family:Space Grotesk,system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.5;-webkit-font-smoothing:antialiased;transition:background-color .4s ease,color .4s ease}.khala-app[data-theme=light],.khala-content-root[data-theme=light]{--bg: #e7d6b2;--bg-2: #e2cfa6;--surface: #f4ecd9;--surface-2: #efe5cd;--surface-3: #e9dcbf;--fg: #2a2520;--muted: #756a55;--faint: #9a8e73;--line: rgba(42, 37, 26, .16);--line-strong: rgba(42, 37, 26, .28);--hairline: rgba(42, 37, 26, .1);--pill-bd: rgba(42, 37, 26, .18);--pill-bg: rgba(42, 37, 26, .04);--accent: #1f57c4;--accent-ink: #1a4aa8;--accent-soft: rgba(31, 87, 196, .11);--accent-line: rgba(31, 87, 196, .3);--accent-complement: #8e4d00;--attn: #b8821a;--attn-ink: #8a6210;--attn-soft: rgba(184, 130, 26, .13);--attn-line: rgba(184, 130, 26, .32);--block: #d23b32;--block-ink: #a52a23;--block-soft: rgba(210, 59, 50, .11);--block-line: rgba(210, 59, 50, .3);--good: #1f9d4d;--good-ink: #167038;--good-soft: rgba(31, 157, 77, .13);--good-line: rgba(31, 157, 77, .3);--super: #8a4fd0;--super-ink: #6d3aa8;--super-soft: rgba(138, 79, 208, .12);--super-line: rgba(138, 79, 208, .3);--ack: #0e9e8e;--ack-soft: rgba(14, 158, 142, .13);--shadow-sm: 0 1px 2px rgba(58, 44, 18, .1);--shadow-lg: 0 44px 80px -40px rgba(58, 44, 18, .3);color-scheme:light}:where(.khala-app,.khala-content-root) *,:where(.khala-app,.khala-content-root) *:before,:where(.khala-app,.khala-content-root) *:after{box-sizing:border-box}:where(.khala-app,.khala-content-root) a{color:var(--accent);text-decoration:none;transition:color .14s ease}:where(.khala-app,.khala-content-root) a:hover{color:var(--accent-ink)}:where(.khala-app,.khala-content-root) button{font:inherit;cursor:pointer}:where(.khala-app,.khala-content-root) ::selection{background:var(--accent-soft)}:where(.khala-app,.khala-content-root) .mono{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}:where(.khala-app,.khala-content-root) .num{font-variant-numeric:tabular-nums slashed-zero;font-feature-settings:"tnum" 1,"zero" 1}:is(.khala-app,.khala-content-root) :is(button,a,[role=button],input[type=search]):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.aiur-action,:where(.aiur-actions) button:not([class]){display:inline-flex;align-items:center;justify-content:center;gap:.4rem;min-height:2.25rem;padding:.5rem .85rem;border:1px solid var(--aiur-accent-strong);border-radius:10px;background:var(--aiur-accent-strong);color:var(--aiur-on-accent);cursor:pointer;font-size:.82rem;font-weight:650;text-decoration:none;transition:transform .14s ease,box-shadow .14s ease}.aiur-action:hover,:where(.aiur-actions) button:not([class]):hover{transform:translateY(-1px);box-shadow:0 8px 20px var(--aiur-accent-soft)}.aiur-action:focus-visible,:where(.aiur-actions) button:not([class]):focus-visible{outline:2px solid var(--aiur-accent);outline-offset:3px}.aiur-action:disabled,.aiur-action[aria-disabled=true],:where(.aiur-actions) button:not([class]):disabled,:where(.aiur-actions) button:not([class])[aria-disabled=true]{opacity:.55;cursor:default}.aiur-action:disabled:hover,.aiur-action[aria-disabled=true]:hover,:where(.aiur-actions) button:not([class]):disabled:hover,:where(.aiur-actions) button:not([class])[aria-disabled=true]:hover{transform:none;box-shadow:none}@media(prefers-reduced-motion:reduce){.aiur-action,:where(.aiur-actions) button:not([class]){transition:none}.aiur-action:hover,:where(.aiur-actions) button:not([class]):hover{transform:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.khala-content-root{min-height:100dvh}.khala-content-main{min-width:0}.aiur-shell__icon-button{display:inline-flex;align-items:center;justify-content:center;flex:none;width:2.05rem;height:2.05rem;padding:0;border:1px solid var(--khala-line);border-radius:50%;background:var(--khala-fill-control);color:var(--khala-ink-muted);cursor:pointer;transition:color .18s ease,border-color .18s ease,background .18s ease}.aiur-shell__icon-button:hover{color:var(--khala-ink);border-color:var(--khala-accent);background:var(--khala-fill-raised)}.aiur-shell__icon-button:disabled{cursor:wait;opacity:.6}.khala-inactive-device{max-width:36rem;margin:clamp(1rem,8vh,5rem) auto}.khala-device-status{padding:clamp(1rem,3vw,2rem);color:var(--khala-ink-muted)}.khala-device-status [role=alert]{color:var(--khala-ink)}.khala-empty-conversation{display:grid;place-items:center;min-height:min(70dvh,600px);color:var(--khala-ink-muted)}.khala-page-frame{max-width:var(--khala-content-measure);margin:0 auto;min-width:0}.khala-page-frame__header h1{font-size:2rem;font-weight:700;margin:.4rem 0}.panel{background:var(--khala-fill-raised);border:1px solid var(--khala-line);border-radius:var(--khala-panel-radius);padding:1.25rem;margin-top:1rem}.status-badge{display:inline-flex;align-items:center;gap:.4rem;border:1px solid var(--khala-line);border-radius:999px;padding:.2rem .6rem;font-family:var(--khala-font-mono);font-size:.8rem}.status-badge--positive{border-color:var(--khala-status-positive)}.status-badge--caution{border-color:var(--khala-status-caution)}.status-badge--critical{border-color:var(--khala-status-critical)}.create-channel__field{display:flex;flex-direction:column;gap:.35rem;margin-bottom:1rem}.create-channel__field input{min-width:0}.create-channel__status{min-height:1.25rem}.create-channel__share{display:flex;flex-direction:column;gap:.5rem;margin-top:1rem;padding-top:1rem;border-top:1px solid var(--khala-line)}.create-channel__share-url{min-width:0;width:100%;overflow-wrap:anywhere;font-family:var(--khala-font-mono)}.timeline{position:relative;display:flex;flex-direction:column;gap:.75rem;min-width:0}.timeline__status{margin:0 1.1rem;padding:.5rem .75rem;border-radius:var(--khala-panel-radius);background:var(--khala-fill-control)}.timeline__retry-history{align-self:flex-start;margin:0 1.1rem}.timeline__history-loading{position:absolute;top:.5rem;left:50%;transform:translate(-50%);z-index:1;pointer-events:none}.timeline__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.75rem;max-height:60vh;overflow-y:auto;min-width:0;position:relative;overflow-anchor:none}.timeline__empty{color:var(--khala-ink-muted);padding:1rem;text-align:center}.message-content__text{margin:0 0 .5rem;white-space:pre-wrap;overflow-wrap:anywhere}.message-content__text:last-child{margin-bottom:0}.message-content__unavailable{color:var(--khala-ink-muted);font-style:italic}.timeline__viewport{position:relative;display:flex;flex-direction:column;flex:1 1 auto;min-height:0}.timeline__jump{position:absolute;left:50%;bottom:.75rem;transform:translate(-50%);z-index:5}.timeline__jump-latest{display:block;padding:.4rem .9rem;border:1px solid var(--line-strong);border-radius:999px;background:var(--surface);color:var(--fg);box-shadow:0 6px 18px -8px #00000073;font:inherit;font-size:.8rem;font-weight:600;white-space:nowrap;cursor:pointer;animation:timelineJumpIn .16s ease-out}.timeline__jump-latest:hover{background:var(--surface-2)}.timeline__jump-latest:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@keyframes timelineJumpIn{0%{opacity:0;transform:translateY(6px)}}@media(prefers-reduced-motion:reduce){.timeline__jump-latest{animation:none}}.timeline__composer{display:flex;flex-direction:column;gap:.5rem;border-top:1px solid var(--khala-line);padding-top:.75rem}.timeline__composer-label{font-family:var(--khala-font-mono);font-size:.8rem;color:var(--khala-ink-muted)}.timeline__composer-input{min-height:3.5rem;resize:vertical;background:var(--khala-fill-control);color:inherit;border:1px solid var(--khala-line);border-radius:.5rem;padding:.5rem;font-family:inherit}@media(max-width:959px){.timeline__list{max-height:50vh}}.channel-page .khala-page-frame{max-width:none}.channel-page .khala-page-frame__header{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.channel-page .khala-page-frame__body{min-width:0}.channel-page .conversation-layout{height:100%;min-height:0}.kh-channel-thread .timeline{height:100%;gap:0;min-height:0}.channel-share{position:relative;display:flex;align-items:center;flex:none}.channel-share .aiur-shell__icon-button:focus-visible{outline:2px solid var(--khala-accent);outline-offset:2px}.channel-share__feedback{position:absolute;right:0;top:calc(100% + .35rem);z-index:2;width:max-content;max-width:min(15rem,80vw);margin:0;padding:.35rem .55rem;border:1px solid var(--khala-line);border-radius:.45rem;background:var(--khala-fill-raised);color:var(--khala-ink);box-shadow:0 4px 12px #0003;font-size:.75rem;line-height:1.35}.channel-share__fallback{width:min(20rem,80vw);max-width:none;display:grid;gap:.35rem}.kh-cname-scrim{position:absolute;inset:0;z-index:40;display:grid;place-items:center;padding:16px;background:#0006}.kh-cname{width:min(380px,100%);box-sizing:border-box;display:flex;flex-direction:column;gap:.55rem;padding:1.2rem 1.1rem 1.05rem;border-radius:14px;background:var(--surface);border:1px solid var(--line-strong);box-shadow:var(--shadow-lg);color:var(--fg)}.kh-cname h2{margin:0;font-size:.98rem;font-weight:700;letter-spacing:-.01em}.kh-cname-note{margin:0;font-size:.84rem;color:var(--muted);overflow-wrap:anywhere}.kh-cname-form{display:flex;flex-direction:column;gap:.45rem;margin-top:.2rem}.kh-cname-field{position:relative;display:flex;align-items:center}.kh-cname-at{position:absolute;left:.7rem;color:var(--faint);font-size:.88rem;pointer-events:none}.kh-cname-field .kh-txt{flex:1;min-width:0;padding-left:1.55rem}.kh-cname-err{margin:0;font-size:.76rem;color:var(--block-ink);overflow-wrap:anywhere}.kh-cname .kh-txt[aria-invalid=true]{border-color:var(--block-line)}.kh-cname-actions{display:flex;justify-content:flex-end;margin-top:.2rem}@media(max-width:480px){.kh-cname-scrim{place-items:start stretch}.kh-cname{width:100%}.kh-cname-actions .kh-btn{flex:1;height:44px}}.kh-owner-tag{display:inline-block;margin-left:.4rem;padding:.1rem .3rem;border:1px solid var(--line-strong);border-radius:4px;font-size:.55rem;letter-spacing:.05em;color:var(--faint);vertical-align:middle}.kh-remove-agents{color:var(--faint);font-size:.75rem;overflow-wrap:anywhere}html,body,#app{height:100%;margin:0}body{overflow:hidden;background:#16171a;color:#edeef0;font-family:Space Grotesk,system-ui,-apple-system,Segoe UI,sans-serif}button,input,textarea{font:inherit}
@@ -5,8 +5,13 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
6
  <meta name="color-scheme" content="dark light" />
7
7
  <title>Khala · local</title>
8
- <script type="module" crossorigin src="/assets/local-CVA9799w.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/local-DHYvcQG0.css">
8
+ <!-- The splash page's favicon (src/landing/public), bundled by Vite so the local app shows it too. -->
9
+ <link rel="icon" href="/assets/favicon-zCD0pKtT.ico" sizes="any" />
10
+ <link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32-B9Ubw1Dx.png" />
11
+ <link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16-D5waNSZD.png" />
12
+ <link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon-Du9V6qit.png" />
13
+ <script type="module" crossorigin src="/assets/local-C1vz22ps.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/local-DdjwMERJ.css">
10
15
  </head>
11
16
  <body>
12
17
  <div id="app"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "khala-cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.5",
4
4
  "description": "Khala channels for Claude Code, Codex and Cursor sessions: the khala MCP server, delivery hooks and local channels.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/aiur-team/khala/tree/main/packages/agent#readme",
@@ -1,455 +0,0 @@
1
- import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
2
-
3
- // ../contracts/src/delivery/decode.ts
4
- var MAX_IDENTIFIER_BYTES = 512;
5
- var DecodeFailure = class extends Error {
6
- code;
7
- field;
8
- constructor(field, code) {
9
- super(`${field || "<root>"}: ${code}`);
10
- this.name = "DecodeFailure";
11
- this.code = code;
12
- this.field = field;
13
- }
14
- };
15
- function fail(field, code) {
16
- throw new DecodeFailure(field, code);
17
- }
18
- function decodeWith(read) {
19
- try {
20
- return { ok: true, value: read() };
21
- } catch (error) {
22
- if (error instanceof DecodeFailure) return { ok: false, code: error.code, field: error.field };
23
- return { ok: false, code: "invalid_field", field: "" };
24
- }
25
- }
26
- function utf8Length(value) {
27
- let bytes = 0;
28
- for (const character of value) {
29
- const codePoint = character.codePointAt(0) ?? 0;
30
- if (codePoint < 128) bytes += 1;
31
- else if (codePoint < 2048) bytes += 2;
32
- else if (codePoint < 65536) bytes += 3;
33
- else bytes += 4;
34
- }
35
- return bytes;
36
- }
37
- function isWellFormed(value) {
38
- for (let index = 0; index < value.length; index += 1) {
39
- const unit = value.charCodeAt(index);
40
- if (unit >= 55296 && unit <= 56319) {
41
- const next = value.charCodeAt(index + 1);
42
- if (!(next >= 56320 && next <= 57343)) return false;
43
- index += 1;
44
- } else if (unit >= 56320 && unit <= 57343) {
45
- return false;
46
- }
47
- }
48
- return true;
49
- }
50
- var CONTROL = /[\u0000-\u001f\u007f-\u009f]/;
51
- function identifier(input, field) {
52
- if (typeof input !== "string") fail(field, "invalid_field");
53
- if (!isWellFormed(input) || input.length === 0 || CONTROL.test(input)) fail(field, "invalid_field");
54
- if (utf8Length(input) > MAX_IDENTIFIER_BYTES) fail(field, "limit_exceeded");
55
- return input;
56
- }
57
- function literal(input, field, allowed) {
58
- if (!allowed.includes(input)) fail(field, "invalid_field");
59
- return input;
60
- }
61
-
62
- // ../contracts/src/delivery/ids.ts
63
- function readId(input, field) {
64
- return identifier(input, field);
65
- }
66
- var idDecoder = () => (input) => decodeWith(() => readId(input, ""));
67
- var decodeOwnerId = idDecoder();
68
- var decodeParticipantId = idDecoder();
69
- var decodeDeviceId = idDecoder();
70
- var decodeBindingId = idDecoder();
71
- var decodeRoomId = idDecoder();
72
- var decodeEventId = idDecoder();
73
- var decodeCommandId = idDecoder();
74
- var decodeReleaseId = idDecoder();
75
- var decodeReceiptId = idDecoder();
76
- var decodeAuthorizationId = idDecoder();
77
- var decodeOperationId = idDecoder();
78
- var decodeCausalRootId = idDecoder();
79
-
80
- // ../contracts/src/delivery/listening-mode.ts
81
- var LISTENING_MODES = ["steer", "sync", "async"];
82
- function decodeListeningMode(input) {
83
- return decodeWith(() => literal(input, "", LISTENING_MODES));
84
- }
85
-
86
- // ../contracts/src/messaging/decode.ts
87
- var MAX_IDENTIFIER_BYTES2 = 512;
88
- var DecodeFailure2 = class extends Error {
89
- path;
90
- code;
91
- constructor(path, code) {
92
- super(`${path || "<root>"}: ${code}`);
93
- this.name = "DecodeFailure";
94
- this.path = path;
95
- this.code = code;
96
- }
97
- };
98
- function fail2(path, code) {
99
- throw new DecodeFailure2(path, code);
100
- }
101
- function decodeWith2(read) {
102
- try {
103
- return { ok: true, value: read() };
104
- } catch (error) {
105
- if (error instanceof DecodeFailure2) return { ok: false, error: { path: error.path, code: error.code } };
106
- throw error;
107
- }
108
- }
109
- var join = (path, key) => typeof key === "number" ? `${path}[${key}]` : path ? `${path}.${key}` : key;
110
- function object2(input, path, keys) {
111
- if (typeof input !== "object" || input === null || Array.isArray(input)) fail2(path, "not_object");
112
- const prototype = Object.getPrototypeOf(input);
113
- if (prototype !== Object.prototype && prototype !== null) fail2(path, "not_object");
114
- const record2 = input;
115
- for (const key of Object.keys(record2)) if (!keys.includes(key)) fail2(join(path, key), "unknown_field");
116
- for (const key of keys) if (!Object.hasOwn(record2, key)) fail2(join(path, key), "missing_field");
117
- return { path, field: (key) => record2[key], at: (key) => join(path, key) };
118
- }
119
- function array(input, path) {
120
- if (!Array.isArray(input)) fail2(path, "wrong_type");
121
- return input;
122
- }
123
- function elementPath(path, index) {
124
- return join(path, index);
125
- }
126
- function utf8Length2(value) {
127
- let bytes = 0;
128
- for (const char of value) {
129
- const code = char.codePointAt(0) ?? 0;
130
- bytes += code < 128 ? 1 : code < 2048 ? 2 : code < 65536 ? 3 : 4;
131
- }
132
- return bytes;
133
- }
134
- function isWellFormed2(value) {
135
- for (let index = 0; index < value.length; index += 1) {
136
- const unit = value.charCodeAt(index);
137
- if (unit >= 55296 && unit <= 56319) {
138
- const next = value.charCodeAt(index + 1);
139
- if (!(next >= 56320 && next <= 57343)) return false;
140
- index += 1;
141
- } else if (unit >= 56320 && unit <= 57343) return false;
142
- }
143
- return true;
144
- }
145
- var CONTROL2 = /[\u0000-\u001f\u007f-\u009f]/;
146
- var INVISIBLE = /[\u061c\u200b\u200e\u200f\u202a-\u202e\u2060\u2066-\u2069\ufeff]/;
147
- function text(input, path, maxBytes) {
148
- if (typeof input !== "string") fail2(path, "wrong_type");
149
- if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) fail2(path, "invalid_limits");
150
- if (!isWellFormed2(input)) fail2(path, "malformed_unicode");
151
- if (utf8Length2(input) > maxBytes) fail2(path, "too_long");
152
- if (input.includes("\0")) fail2(path, "control_character");
153
- return input;
154
- }
155
- function label(input, path, maxBytes) {
156
- const value = text(input, path, maxBytes);
157
- if (CONTROL2.test(value)) fail2(path, "control_character");
158
- return value;
159
- }
160
- function displayText(input, path, maxBytes) {
161
- const value = label(input, path, maxBytes);
162
- if (INVISIBLE.test(value)) fail2(path, "control_character");
163
- return value;
164
- }
165
- function identifier2(input, path) {
166
- const value = label(input, path, MAX_IDENTIFIER_BYTES2);
167
- if (value.length === 0) fail2(path, "empty");
168
- return value;
169
- }
170
- function nullable2(input, read) {
171
- return input === null ? null : read(input);
172
- }
173
- function literal2(input, path, allowed) {
174
- if (!allowed.includes(input)) fail2(path, typeof input === typeof allowed[0] ? "invalid_value" : "wrong_type");
175
- return input;
176
- }
177
- function version2(input, path) {
178
- if (input !== 1) fail2(path, "unsupported_version");
179
- return 1;
180
- }
181
- function safeInteger2(input, path) {
182
- if (typeof input !== "number") fail2(path, "wrong_type");
183
- if (!Number.isSafeInteger(input)) fail2(path, "unsafe_integer");
184
- if (input < 0) fail2(path, "invalid_value");
185
- return input;
186
- }
187
- var UTC_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?Z$/;
188
- function utcTimestamp2(input, path) {
189
- if (typeof input !== "string") fail2(path, "wrong_type");
190
- const match = UTC_TIMESTAMP.exec(input);
191
- if (!match) fail2(path, "invalid_value");
192
- const [year, month, day, hour, minute, second] = match.slice(1).map(Number);
193
- const date = /* @__PURE__ */ new Date(0);
194
- date.setUTCFullYear(year, month - 1, day);
195
- date.setUTCHours(hour, minute, second, 0);
196
- if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day || date.getUTCHours() !== hour || date.getUTCMinutes() !== minute || date.getUTCSeconds() !== second) fail2(path, "invalid_value");
197
- return input;
198
- }
199
-
200
- // ../contracts/src/messaging/agent-names.ts
201
- var MAX_AGENT_NAME_BYTES = 80;
202
- var unsafe = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028-\u202e\u2060-\u2069\ufeff]/u;
203
- var reserved = /\b(?:admin(?:istrator)?|system|khala|moderator|owner|human|security|support|official)\b/iu;
204
- function validateAgentName(input) {
205
- if (typeof input !== "string") return { ok: false, error: "blank" };
206
- const name = input.trim().normalize("NFC");
207
- if (!name) return { ok: false, error: "blank" };
208
- if (unsafe.test(name)) return { ok: false, error: "invalid_characters" };
209
- if (new TextEncoder().encode(name).byteLength > MAX_AGENT_NAME_BYTES) return { ok: false, error: "too_long" };
210
- if (reserved.test(name.normalize("NFKC"))) return { ok: false, error: "reserved" };
211
- return { ok: true, name };
212
- }
213
-
214
- // ../contracts/src/m1/agent-join.ts
215
- var HARNESSES = ["claude", "codex", "cursor"];
216
- var M1_LABEL_MAX_BYTES = 512;
217
- var agentConfirmPagePath = (id) => `/agent/confirm?joinId=${encodeURIComponent(id)}`;
218
- function readHarness(input, path) {
219
- return literal2(input, path, HARNESSES);
220
- }
221
- function readHttpUrl(input, path) {
222
- if (typeof input !== "string") fail2(path, "wrong_type");
223
- let url;
224
- try {
225
- url = new URL(input);
226
- } catch {
227
- fail2(path, "invalid_value");
228
- }
229
- if (url.username || url.password || url.hash || !(url.protocol === "https:" || url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))) fail2(path, "invalid_value");
230
- return input;
231
- }
232
- function readMatrixUserId(input, path) {
233
- const value = identifier2(input, path);
234
- if (!/^@[^\s:]+:\S+$/u.test(value)) fail2(path, "invalid_value");
235
- return value;
236
- }
237
- function readRoomId(input, path) {
238
- const value = identifier2(input, path);
239
- if (!/^!\S+$/u.test(value)) fail2(path, "invalid_value");
240
- return value;
241
- }
242
- var validAgentSessionId = (value) => typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/u.test(value);
243
- var validAgentRejoinSecret = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{43}$/u.test(value);
244
-
245
- // ../contracts/src/m1/listening-mode.ts
246
- var LISTENING_MODE_COMMAND_TYPE = "com.khala.listening_mode.v1";
247
- var LISTENING_MODE_MEMBER_KEY = "com.khala.listening_mode";
248
- var DEFAULT_LISTENING_MODE = "sync";
249
- function decodeListeningModeCommand(input) {
250
- return decodeWith2(() => {
251
- const r = object2(input, "", ["v", "agent", "mode"]);
252
- return {
253
- v: version2(r.field("v"), r.at("v")),
254
- agent: readMatrixUserId(r.field("agent"), r.at("agent")),
255
- mode: literal2(r.field("mode"), r.at("mode"), LISTENING_MODES)
256
- };
257
- });
258
- }
259
- function memberListeningMode(content) {
260
- const value = typeof content === "object" && content !== null ? content[LISTENING_MODE_MEMBER_KEY] : void 0;
261
- const decoded = decodeListeningMode(value);
262
- return decoded.ok ? decoded.value : DEFAULT_LISTENING_MODE;
263
- }
264
-
265
- // ../contracts/src/m1/channel-event.ts
266
- var CHANNEL_EVENT_TYPE = "com.khala.event.v1";
267
- var CHANNEL_EVENT_STATUSES = ["info", "pending", "success", "failure", "attention"];
268
- var MAX_CHANNEL_EVENT_BYTES = 4096;
269
- function record(input, path) {
270
- if (typeof input !== "object" || input === null || Array.isArray(input)) fail2(path, "not_object");
271
- const prototype = Object.getPrototypeOf(input);
272
- if (prototype !== Object.prototype && prototype !== null) fail2(path, "not_object");
273
- const value = input;
274
- return {
275
- has: (key) => Object.hasOwn(value, key) && value[key] !== void 0,
276
- field: (key) => Object.hasOwn(value, key) ? value[key] : fail2(path ? `${path}.${key}` : key, "missing_field"),
277
- at: (key) => path ? `${path}.${key}` : key
278
- };
279
- }
280
- function nonempty(value, path) {
281
- if (!value.length) fail2(path, "empty");
282
- return value;
283
- }
284
- function display(input, path, maxBytes, maxPoints) {
285
- const value = nonempty(displayText(input, path, maxBytes), path);
286
- if ([...value].length > maxPoints) fail2(path, "too_long");
287
- return value;
288
- }
289
- function matching(value, path, pattern) {
290
- if (!pattern.test(value)) fail2(path, "invalid_value");
291
- return value;
292
- }
293
- function safely(read) {
294
- try {
295
- return read();
296
- } catch {
297
- return { ok: false, error: { path: "", code: "invalid_value" } };
298
- }
299
- }
300
- function decodeChannelEvent(raw) {
301
- return safely(() => decodeWith2(() => {
302
- let serialized;
303
- try {
304
- serialized = JSON.stringify(raw);
305
- } catch {
306
- fail2("", "invalid_value");
307
- }
308
- if (serialized !== void 0 && utf8Length2(serialized) > MAX_CHANNEL_EVENT_BYTES) fail2("", "too_long");
309
- const r = record(raw, "");
310
- const v = version2(r.field("v"), "v");
311
- const kind = matching(nonempty(label(r.field("kind"), "kind", 128), "kind"), "kind", /^[a-z0-9_-]+(\.[a-z0-9_-]+)*$/);
312
- const summary = display(r.field("summary"), "summary", 800, 200);
313
- if (!summary.trim()) fail2("summary", "empty");
314
- const body = label(r.field("body"), "body", 1024);
315
- return {
316
- v,
317
- kind,
318
- summary,
319
- body,
320
- ...r.has("status") ? { status: literal2(r.field("status"), "status", CHANNEL_EVENT_STATUSES) } : {},
321
- ...r.has("subject") ? { subject: readSubject(r.field("subject")) } : {},
322
- ...r.has("actor") ? { actor: display(r.field("actor"), "actor", 256, 64) } : {},
323
- ...r.has("url") ? { url: readUrl(r.field("url")) } : {},
324
- ...r.has("occurred_at") ? { occurred_at: utcTimestamp2(r.field("occurred_at"), "occurred_at") } : {},
325
- ...r.has("source") ? { source: readSource(r.field("source")) } : {},
326
- ...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {}
327
- };
328
- }));
329
- }
330
- function readSubject(input) {
331
- const r = record(input, "subject");
332
- let pr;
333
- if (r.has("pr")) {
334
- pr = safeInteger2(r.field("pr"), r.at("pr"));
335
- if (pr === 0) fail2(r.at("pr"), "invalid_value");
336
- }
337
- let branch;
338
- if (r.has("branch")) {
339
- branch = nonempty(label(r.field("branch"), r.at("branch"), 255), r.at("branch"));
340
- if (branch.startsWith("refs/")) fail2(r.at("branch"), "invalid_value");
341
- }
342
- return {
343
- ...r.has("ticket") ? { ticket: display(r.field("ticket"), r.at("ticket"), 256, 64) } : {},
344
- ...pr !== void 0 ? { pr } : {},
345
- ...branch !== void 0 ? { branch } : {},
346
- ...r.has("repo") ? { repo: matching(label(r.field("repo"), r.at("repo"), 140), r.at("repo"), /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/) } : {},
347
- ...r.has("sha") ? { sha: matching(label(r.field("sha"), r.at("sha"), 64), r.at("sha"), /^[0-9a-f]{7,64}$/) } : {}
348
- };
349
- }
350
- function readSource(input) {
351
- const r = record(input, "source");
352
- return {
353
- system: nonempty(label(r.field("system"), r.at("system"), 32), r.at("system")),
354
- ...r.has("topic") ? { topic: label(r.field("topic"), r.at("topic"), 256) } : {},
355
- ...r.has("event_id") ? { event_id: label(r.field("event_id"), r.at("event_id"), 64) } : {}
356
- };
357
- }
358
- function readUrl(input) {
359
- if (typeof input !== "string") fail2("url", "wrong_type");
360
- if (utf8Length2(input) > 2048) fail2("url", "too_long");
361
- try {
362
- if (new URL(input).protocol !== "https:") fail2("url", "invalid_value");
363
- } catch {
364
- fail2("url", "invalid_value");
365
- }
366
- return input;
367
- }
368
- function formatChannelEventLine(content) {
369
- const { summary, subject } = content;
370
- const head = subject?.ticket ? `${subject.ticket} ${summary}` : summary;
371
- const tail = subject?.branch ?? (subject?.pr !== void 0 ? `PR #${subject.pr}` : void 0);
372
- return tail ? `${head} \xB7 ${tail}` : head;
373
- }
374
- function encodeChannelEvent(input) {
375
- return safely(() => {
376
- const checked = decodeWith2(() => {
377
- record(input, "");
378
- return { ...input, v: 1, body: "" };
379
- });
380
- if (!checked.ok) return checked;
381
- const decoded = decodeChannelEvent(checked.value);
382
- if (!decoded.ok) return decoded;
383
- return decodeChannelEvent({ ...decoded.value, body: formatChannelEventLine(decoded.value) });
384
- });
385
- }
386
- function memberRenameContent(content, previous) {
387
- const oldName = previous?.["displayname"];
388
- const newName = content["displayname"];
389
- if (previous?.["membership"] !== "join" || content["membership"] !== "join" || typeof oldName !== "string" || !oldName.trim() || typeof newName !== "string" || !newName.trim() || oldName === newName) return null;
390
- const encoded = encodeChannelEvent({ kind: "member", summary: `${oldName} is now ${newName}`, status: "info", source: { system: "khala" } });
391
- return encoded.ok ? encoded.value : null;
392
- }
393
- function statusFor(content) {
394
- if (content.status !== void 0) return content.status;
395
- switch (content.kind) {
396
- case "ci.passed":
397
- case "pr.merged":
398
- case "agent.unblocked":
399
- return "success";
400
- case "ci.failed":
401
- return "failure";
402
- case "pr.ready_for_review":
403
- case "pr.parked_ready":
404
- return "pending";
405
- case "agent.paused":
406
- case "agent.blocked":
407
- case "agent.pause.request":
408
- return "attention";
409
- default:
410
- return content.kind.startsWith("agent.attention.") && !content.kind.endsWith(".resolved") ? "attention" : "info";
411
- }
412
- }
413
-
414
- export {
415
- fail2 as fail,
416
- decodeWith2 as decodeWith,
417
- object2 as object,
418
- array,
419
- elementPath,
420
- utf8Length2 as utf8Length,
421
- isWellFormed2 as isWellFormed,
422
- text,
423
- label,
424
- displayText,
425
- identifier2 as identifier,
426
- nullable2 as nullable,
427
- literal2 as literal,
428
- version2 as version,
429
- safeInteger2 as safeInteger,
430
- utcTimestamp2 as utcTimestamp,
431
- reserved,
432
- validateAgentName,
433
- HARNESSES,
434
- M1_LABEL_MAX_BYTES,
435
- agentConfirmPagePath,
436
- readHarness,
437
- readHttpUrl,
438
- readMatrixUserId,
439
- readRoomId,
440
- validAgentSessionId,
441
- validAgentRejoinSecret,
442
- LISTENING_MODES,
443
- decodeListeningMode,
444
- LISTENING_MODE_COMMAND_TYPE,
445
- LISTENING_MODE_MEMBER_KEY,
446
- DEFAULT_LISTENING_MODE,
447
- decodeListeningModeCommand,
448
- memberListeningMode,
449
- CHANNEL_EVENT_TYPE,
450
- decodeChannelEvent,
451
- formatChannelEventLine,
452
- encodeChannelEvent,
453
- memberRenameContent,
454
- statusFor
455
- };