@spencerboucher/switchyard 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +3 -3
  2. package/dist/bridge/lines.js +33 -0
  3. package/dist/bridge/switchyard-terminal.js +59 -22
  4. package/dist/switchyard.mjs +3411 -2527
  5. package/dist/terminal/holder.js +142 -51
  6. package/package.json +1 -1
  7. package/web-dist/apple-touch-icon.png +0 -0
  8. package/web-dist/assets/AutomationView-D7Syv1En.js +2 -0
  9. package/web-dist/assets/AutomationView-D7Syv1En.js.map +1 -0
  10. package/web-dist/assets/Checkbox-D6tRfEeI.js +2 -0
  11. package/web-dist/assets/Checkbox-D6tRfEeI.js.map +1 -0
  12. package/web-dist/assets/Copy-B6XSAIUd.js +2 -0
  13. package/web-dist/assets/Copy-B6XSAIUd.js.map +1 -0
  14. package/web-dist/assets/DangerZone-DfYlxDC1.js +2 -0
  15. package/web-dist/assets/DangerZone-DfYlxDC1.js.map +1 -0
  16. package/web-dist/assets/Field-D-Ty7fKT.js +2 -0
  17. package/web-dist/assets/Field-D-Ty7fKT.js.map +1 -0
  18. package/web-dist/assets/InteractionCard-DF1EcSpm.js +6 -0
  19. package/web-dist/assets/InteractionCard-DF1EcSpm.js.map +1 -0
  20. package/web-dist/assets/Menu-BfOszNC4.js +2 -0
  21. package/web-dist/assets/Menu-BfOszNC4.js.map +1 -0
  22. package/web-dist/assets/Overlay-DUQwh6_b.js +2 -0
  23. package/web-dist/assets/Overlay-DUQwh6_b.js.map +1 -0
  24. package/web-dist/assets/Priority-CHmzfoHg.js +2 -0
  25. package/web-dist/assets/Priority-CHmzfoHg.js.map +1 -0
  26. package/web-dist/assets/{SegmentedControl-BZPzNU08.js → SegmentedControl-C_hEVQMB.js} +2 -2
  27. package/web-dist/assets/{SegmentedControl-BZPzNU08.js.map → SegmentedControl-C_hEVQMB.js.map} +1 -1
  28. package/web-dist/assets/Select-Cfql4Nwu.js +2 -0
  29. package/web-dist/assets/Select-Cfql4Nwu.js.map +1 -0
  30. package/web-dist/assets/Switch-DBfzmqkm.js +2 -0
  31. package/web-dist/assets/Switch-DBfzmqkm.js.map +1 -0
  32. package/web-dist/assets/Tabs-BNuL3_Et.js +184 -0
  33. package/web-dist/assets/Tabs-BNuL3_Et.js.map +1 -0
  34. package/web-dist/assets/TextArea-CKybrQyn.js +2 -0
  35. package/web-dist/assets/TextArea-CKybrQyn.js.map +1 -0
  36. package/web-dist/assets/TextLink-OzzyP2-p.js +2 -0
  37. package/web-dist/assets/TextLink-OzzyP2-p.js.map +1 -0
  38. package/web-dist/assets/arrow-down-C-iLrN8I.js +2 -0
  39. package/web-dist/assets/arrow-down-C-iLrN8I.js.map +1 -0
  40. package/web-dist/assets/arrow-up-Dj-VTKx4.js +2 -0
  41. package/web-dist/assets/arrow-up-Dj-VTKx4.js.map +1 -0
  42. package/web-dist/assets/attention-V86Gye3I.js +2 -0
  43. package/web-dist/assets/attention-V86Gye3I.js.map +1 -0
  44. package/web-dist/assets/automations-Cw5Gacgm.js +2 -0
  45. package/web-dist/assets/automations-Cw5Gacgm.js.map +1 -0
  46. package/web-dist/assets/board-B8X7TYYR.js +10 -0
  47. package/web-dist/assets/board-B8X7TYYR.js.map +1 -0
  48. package/web-dist/assets/code-BKroYJmR.js +12 -0
  49. package/web-dist/assets/code-BKroYJmR.js.map +1 -0
  50. package/web-dist/assets/describe-D6KLGKWa.js +5 -0
  51. package/web-dist/assets/describe-D6KLGKWa.js.map +1 -0
  52. package/web-dist/assets/enroll-DwT7AcuS.js +2 -0
  53. package/web-dist/assets/enroll-DwT7AcuS.js.map +1 -0
  54. package/web-dist/assets/index-B3F7WcYf.css +2 -0
  55. package/web-dist/assets/index-hxvDvCS7.js +12 -0
  56. package/web-dist/assets/index-hxvDvCS7.js.map +1 -0
  57. package/web-dist/assets/logic-B46fwD-8.js +2 -0
  58. package/web-dist/assets/logic-B46fwD-8.js.map +1 -0
  59. package/web-dist/assets/more-DQR5uu1c.js +2 -0
  60. package/web-dist/assets/more-DQR5uu1c.js.map +1 -0
  61. package/web-dist/assets/queue-DUg1rS8t.js +2 -0
  62. package/web-dist/assets/queue-DUg1rS8t.js.map +1 -0
  63. package/web-dist/assets/repo-XzzzEI0d.js +2 -0
  64. package/web-dist/assets/repo-XzzzEI0d.js.map +1 -0
  65. package/web-dist/assets/server-BqZ-w6M8.js +2 -0
  66. package/web-dist/assets/server-BqZ-w6M8.js.map +1 -0
  67. package/web-dist/assets/settings-DyUu0tJM.js +8 -0
  68. package/web-dist/assets/settings-DyUu0tJM.js.map +1 -0
  69. package/web-dist/assets/states-ZhrxQa3K.js +56 -0
  70. package/web-dist/assets/states-ZhrxQa3K.js.map +1 -0
  71. package/web-dist/assets/terminal-BOV_MXPZ.js +2 -0
  72. package/web-dist/assets/terminal-BOV_MXPZ.js.map +1 -0
  73. package/web-dist/assets/terminal-login-S5CAd5xA.js +2 -0
  74. package/web-dist/assets/terminal-login-S5CAd5xA.js.map +1 -0
  75. package/web-dist/assets/useBackTo-BIrCq3W2.js +2 -0
  76. package/web-dist/assets/useBackTo-BIrCq3W2.js.map +1 -0
  77. package/web-dist/assets/useNow-Dj7oEiwn.js +2 -0
  78. package/web-dist/assets/useNow-Dj7oEiwn.js.map +1 -0
  79. package/web-dist/assets/useResource-CDGSq2At.js +2 -0
  80. package/web-dist/assets/useResource-CDGSq2At.js.map +1 -0
  81. package/web-dist/icon-192.png +0 -0
  82. package/web-dist/icon-512.png +0 -0
  83. package/web-dist/icon.svg +20 -8
  84. package/web-dist/index.html +3 -4
  85. package/web-dist/manifest.webmanifest +1 -1
  86. package/web-dist/maskable-512.png +0 -0
  87. package/web-dist/sw.js +1 -1
  88. package/web-dist/sw.js.map +1 -1
  89. package/web-dist/assets/AutomationView-GCthHkym.js +0 -2
  90. package/web-dist/assets/AutomationView-GCthHkym.js.map +0 -1
  91. package/web-dist/assets/Badge-CEMI3YyI.js +0 -2
  92. package/web-dist/assets/Badge-CEMI3YyI.js.map +0 -1
  93. package/web-dist/assets/InteractionCard-DaLqafmA.js +0 -6
  94. package/web-dist/assets/InteractionCard-DaLqafmA.js.map +0 -1
  95. package/web-dist/assets/Menu-BcKiEc6X.js +0 -2
  96. package/web-dist/assets/Menu-BcKiEc6X.js.map +0 -1
  97. package/web-dist/assets/Tabs-COH5EMql.js +0 -184
  98. package/web-dist/assets/Tabs-COH5EMql.js.map +0 -1
  99. package/web-dist/assets/TextArea-CeMEPZn4.js +0 -2
  100. package/web-dist/assets/TextArea-CeMEPZn4.js.map +0 -1
  101. package/web-dist/assets/arrow-left-C6YWM6y6.js +0 -2
  102. package/web-dist/assets/arrow-left-C6YWM6y6.js.map +0 -1
  103. package/web-dist/assets/attention-BAdea2kA.js +0 -2
  104. package/web-dist/assets/attention-BAdea2kA.js.map +0 -1
  105. package/web-dist/assets/automations-DSFUzB0w.js +0 -2
  106. package/web-dist/assets/automations-DSFUzB0w.js.map +0 -1
  107. package/web-dist/assets/board-eQ3H8yCp.js +0 -10
  108. package/web-dist/assets/board-eQ3H8yCp.js.map +0 -1
  109. package/web-dist/assets/code-D7JmYMKe.js +0 -13
  110. package/web-dist/assets/code-D7JmYMKe.js.map +0 -1
  111. package/web-dist/assets/copy-oWgGHmkS.js +0 -2
  112. package/web-dist/assets/copy-oWgGHmkS.js.map +0 -1
  113. package/web-dist/assets/describe-C1YimBXJ.js +0 -5
  114. package/web-dist/assets/describe-C1YimBXJ.js.map +0 -1
  115. package/web-dist/assets/dist-B_RpNOcK.js +0 -56
  116. package/web-dist/assets/dist-B_RpNOcK.js.map +0 -1
  117. package/web-dist/assets/enroll-1OCy5r50.js +0 -2
  118. package/web-dist/assets/enroll-1OCy5r50.js.map +0 -1
  119. package/web-dist/assets/index-BhpEXLav.js +0 -11
  120. package/web-dist/assets/index-BhpEXLav.js.map +0 -1
  121. package/web-dist/assets/index-DUeOwDZ6.css +0 -2
  122. package/web-dist/assets/logic-CBvFOyIo.js +0 -2
  123. package/web-dist/assets/logic-CBvFOyIo.js.map +0 -1
  124. package/web-dist/assets/more-RjVyxPaz.js +0 -2
  125. package/web-dist/assets/more-RjVyxPaz.js.map +0 -1
  126. package/web-dist/assets/now-CDjeFSLD.js +0 -2
  127. package/web-dist/assets/now-CDjeFSLD.js.map +0 -1
  128. package/web-dist/assets/plus-BLP-wIYD.js +0 -2
  129. package/web-dist/assets/plus-BLP-wIYD.js.map +0 -1
  130. package/web-dist/assets/save-DEvZPWlS.js +0 -2
  131. package/web-dist/assets/save-DEvZPWlS.js.map +0 -1
  132. package/web-dist/assets/send-BKjswHxB.js +0 -2
  133. package/web-dist/assets/send-BKjswHxB.js.map +0 -1
  134. package/web-dist/assets/server-SxFxIScj.js +0 -2
  135. package/web-dist/assets/server-SxFxIScj.js.map +0 -1
  136. package/web-dist/assets/settings-tH4UuIfJ.js +0 -7
  137. package/web-dist/assets/settings-tH4UuIfJ.js.map +0 -1
  138. package/web-dist/assets/shared-CRX6KSBm.js +0 -3
  139. package/web-dist/assets/shared-CRX6KSBm.js.map +0 -1
  140. package/web-dist/assets/sliders-horizontal-DAoirila.js +0 -2
  141. package/web-dist/assets/sliders-horizontal-DAoirila.js.map +0 -1
  142. package/web-dist/assets/states-DXozulGZ.js +0 -2
  143. package/web-dist/assets/states-DXozulGZ.js.map +0 -1
  144. package/web-dist/assets/terminal-login-CW2rE50W.js +0 -2
  145. package/web-dist/assets/terminal-login-CW2rE50W.js.map +0 -1
  146. package/web-dist/assets/trash-C6X2OLrI.js +0 -2
  147. package/web-dist/assets/trash-C6X2OLrI.js.map +0 -1
  148. package/web-dist/assets/useNow-C_B7JgMM.js +0 -2
  149. package/web-dist/assets/useNow-C_B7JgMM.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ import{_ as e,m as t,t as n}from"./jsx-runtime-D13aM9HY.js";import{St as r,_t as i,et as a,v as o,vt as s,yt as c,z as l}from"./states-ZhrxQa3K.js";import{X as u,b as d}from"./index-hxvDvCS7.js";var f=e(t(),1),p=n();function m({count:e}){return e>0?(0,p.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-sm text-warning`,children:[(0,p.jsx)(o,{"aria-hidden":!0,className:`size-4 shrink-0`}),e===1?`1 failure`:`${e} failures`]}):(0,p.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-sm text-muted`,children:[(0,p.jsx)(u,{"aria-hidden":!0,className:`size-4 shrink-0`}),`No failures`]})}var h=(e,t=``)=>`/api/automations/${encodeURIComponent(e)}${t}`,g=r()(e=>({byId:{},deleted:{},put:t=>e(e=>({byId:{...e.byId,[t.id]:t}})),putMany:t=>e(e=>{let n={...e.byId};for(let e of t)n[e.id]=e;return{byId:n}}),remove:t=>e(e=>{let n={...e.byId};return delete n[t],{byId:n,deleted:{...e.deleted,[t]:!0}}})}));function _(e,t){return e?t&&t.updatedAt>e.updatedAt?t:e:t}function ee(){let e=l(e=>e.automations),t=g(e=>e.byId),n=g(e=>e.deleted);return(0,f.useMemo)(()=>{let r={};for(let i of new Set([...Object.keys(e),...Object.keys(t)])){if(n[i])continue;let a=_(e[i],t[i]);a&&(r[i]=a)}return r},[e,t,n])}function te(e){let t=l(t=>e?t.automations[e]:void 0),n=g(t=>e?t.byId[e]:void 0);return g(t=>e?t.deleted[e]:void 0)?void 0:_(t,n)}function ne(){let[e,t]=(0,f.useState)({});return{busy:e,toggle:(0,f.useCallback)(async(e,n)=>{t(t=>({...t,[e.id]:!0}));try{let t=await i(h(e.id),{enabled:n});t&&typeof t==`object`&&`id`in t&&g.getState().put(t),d.success(`${e.name} ${n?`enabled`:`disabled`}`)}catch(t){d.error(`Could not ${n?`enable`:`disable`} ${e.name}: ${c(t)}`)}finally{t(t=>({...t,[e.id]:!1}))}},[])}}function re(e){let[t,n]=(0,f.useState)({});return{busy:t,run:(0,f.useCallback)(async t=>{n(e=>({...e,[t.id]:!0}));try{let n=await s(h(t.id,`/run`)),r=n&&typeof n==`object`?n.state:void 0;d.success(r&&r!==`fired`?`${t.name}: occurrence recorded (${r.replace(/_/g,` `)})`:`${t.name} started`),e?.()}catch(e){d.error(`Could not run ${t.name}: ${c(e)}`)}finally{n(e=>({...e,[t.id]:!1}))}},[e])}}var ie={manual:`Manual`,once:`Once`,cron:`Schedule`,webhook:`Webhook`,dependency:`Dependency`},v=[{value:`fresh`,label:`Fresh`,explanation:`Fresh: a new task per occurrence`},{value:`continue`,label:`Continue`,explanation:`Continue: reuse the task with the same grouping key`},{value:`watch`,label:`Watch`,explanation:`Watch: only raises attention when something relevant changed`}],y=[{value:`skip`,label:`Skip`,explanation:`Skip: drop the occurrence while earlier work is still open`},{value:`queue_one`,label:`Queue one`,explanation:`Queue one: keep a single pending occurrence and fire it when the open work ends`},{value:`append`,label:`Append`,explanation:`Append: add the new objective to the open task (as a follow-up if it is running)`}],ae=[{value:`skip`,label:`Skip`,explanation:`Skip: occurrences missed while the coordinator was down are recorded and skipped`},{value:`run_once`,label:`Run once`,explanation:`Run once: on return, fire the newest missed occurrence once`}];function b(e){return v.find(t=>t.value===e)?.label??e}var x=[`{{date}}`,`{{time}}`,`{{occurrence}}`,`{{payload.<path>}}`];function S(e){return e.length<=1?e[0]??``:`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}function C(e){return String(e).padStart(2,`0`)}function w(e){let t=e%100;if(t>=11&&t<=13)return`${e}th`;switch(e%10){case 1:return`${e}st`;case 2:return`${e}nd`;case 3:return`${e}rd`;default:return`${e}th`}}function T(e){return e&&e[0].toUpperCase()+e.slice(1)}function E(e){return e.split(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0)}var D=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`],O=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],k=[{name:`Minute`,min:0,max:59},{name:`Hour`,min:0,max:23},{name:`Day of month`,min:1,max:31},{name:`Month`,min:1,max:12,names:O.map(e=>e.slice(0,3).toLowerCase())},{name:`Day of week`,min:0,max:7,names:D.map(e=>e.slice(0,3).toLowerCase())}];function A(e,t){let n=e.toLowerCase();if(t.names){let e=t.names.indexOf(n);if(e>=0)return t.min+e}if(!/^\d+$/.test(e))return`"${e}" is not a number`;let r=Number(e);return r<t.min||r>t.max?`${r} is out of range ${t.min}–${t.max}`:r}function oe(e,t){if(e===`*`||e===`?`)return{any:!0,values:[],step:null,extended:!1};if(/[LW#]/i.test(e)&&!t.names?.some(t=>e.toLowerCase().includes(t)))return/^[0-9A-Za-z*?,\-/#]+$/.test(e)?{any:!1,values:[],step:null,extended:!0}:`"${e}" is not valid`;let n=e.split(`,`),r=new Set,i=null;for(let e of n){if(!e)return`empty list item`;let[a,o,s]=e.split(`/`);if(s!==void 0)return`"${e}" has more than one step`;let c=1;if(o!==void 0){if(!/^\d+$/.test(o)||Number(o)<1)return`"${o}" is not a valid step`;c=Number(o)}let l,u;if(a===`*`||a===`?`)l=t.min,u=t.max;else if(a?.includes(`-`)){let[e,n]=a.split(`-`),r=A(e??``,t),i=A(n??``,t);if(typeof r==`string`)return r;if(typeof i==`string`)return i;if(r>i)return`range ${a} runs backwards`;l=r,u=i}else{let e=A(a??``,t);if(typeof e==`string`)return e;l=e,u=o===void 0?e:t.max}for(let e=l;e<=u;e+=c)r.add(e);n.length===1&&o!==void 0&&!a?.includes(`-`)&&(i={every:c,start:l})}let a=[...r].sort((e,t)=>e-t);t.max===7&&(a=[...new Set(a.map(e=>e%7))].sort((e,t)=>e-t));let o=t.max===7?7:t.max-t.min+1;return a.length===o&&!i?{any:!0,values:[],step:null,extended:!1}:{any:!1,values:a,step:i,extended:!1}}function j(e){let t=e.trim();if(!t)return`Enter a cron expression`;let n=t.split(/\s+/);if(n.length!==5)return`Expected 5 fields (minute hour day-of-month month day-of-week), got ${n.length}`;let r=[];for(let e=0;e<5;e++){let t=k[e],i=oe(n[e],t);if(typeof i==`string`)return`${t.name}: ${i}`;r.push(i)}return r}function M(e){let t=j(e);return typeof t==`string`?t:null}function se(e){if(!e.trim())return`Enter a timezone`;try{return new Intl.DateTimeFormat(void 0,{timeZone:e.trim()}),null}catch{return`Unknown timezone "${e}"`}}function N(e){for(let t=1;t<e.length;t++)if(e[t]!==e[t-1]+1)return!1;return e.length>0}function P(e,t){if(e.any&&t.any)return{kind:`freq`,text:`Every minute`};if(e.step&&e.step.start===0&&t.any)return{kind:`freq`,text:e.step.every===1?`Every minute`:`Every ${e.step.every} minutes`};if(e.any)return t.step||t.values.length===0?null:N(t.values)?{kind:`freq`,text:`Every minute from ${C(t.values[0])}:00 to ${C(t.values[t.values.length-1])}:59`}:null;if(t.any)return e.step?null:e.values.length===1&&e.values[0]===0?{kind:`freq`,text:`Every hour`}:{kind:`freq`,text:`Every hour at ${S(e.values.map(e=>`:${C(e)}`))}`};if(t.step&&t.step.start===0&&e.values.length===1&&!e.step){let n=e.values[0]===0?``:` at :${C(e.values[0])}`;return{kind:`freq`,text:t.step.every===1?`Every hour${n}`:`Every ${t.step.every} hours${n}`}}if(e.values.length*t.values.length<=6){let n=[];for(let r of t.values)for(let t of e.values)n.push(`${C(r)}:${C(t)}`);return{kind:`at`,text:S(n)}}if(!N(t.values))return null;let n=t.values[0],r=t.values[t.values.length-1];if(e.step&&e.step.start===0)return{kind:`freq`,text:`Every ${e.step.every} minutes from ${C(n)}:00 to ${C(r)}:59`};if(e.values.length===1){let t=C(e.values[0]);return{kind:`freq`,text:`Every hour from ${C(n)}:${t} to ${C(r)}:${t}`}}return null}function F(e,t){return(e+6)%7-(t+6)%7}function I(e,t,n){if(!e.any&&!n.any)return null;let r=t.any?null:S(t.values.map(e=>O[e-1])),i=r?` in ${r}`:``;if(!n.any){let e=[...n.values].sort(F),t=e.join(`,`);if(t===`1,2,3,4,5`)return{lead:`Every weekday${i}`,qual:` on weekdays${i}`};if(t===`6,0`)return{lead:`Every Saturday and Sunday${i}`,qual:` on weekends${i}`};let r=e.map(e=>D[e]);return{lead:`Every ${S(r)}${i}`,qual:` on ${S(r.map(e=>`${e}s`))}${i}`}}if(!e.any){if(e.values.length>5)return null;let t=S(e.values.map(w)),n=r||`every month`;return{lead:`On the ${t} of ${n}`,qual:` on the ${t} of ${n}`}}return{lead:`Every day${i}`,qual:i}}function L(e,t){let n=j(e);if(typeof n==`string`||n.some(e=>e.extended))return null;let[r,i,a,o,s]=n,c=P(r,i),l=I(a,o,s);if(!c||!l)return null;let u=c.kind===`at`?`${l.lead} at ${c.text}`:`${c.text}${l.qual}`;return t?`${u} (${t})`:u}function R(e,t){return L(e,t)??`Cron ${e.trim()} (${t})`}function z(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`})}function B(e,t={}){let n=t.formatDate??z;switch(e.kind){case`manual`:return`Manual`;case`once`:return e.at&&!Number.isNaN(Date.parse(e.at))?`Once at ${n(e.at)}`:`Once (no time chosen)`;case`cron`:return R(e.expr,e.timezone);case`webhook`:return`Webhook`;case`dependency`:{let n=e.taskId?t.taskTitle?.(e.taskId):void 0;return n?`When "${n}" is done`:e.taskId?`When a deleted task is done`:`When a task is done`}}}function V(e,t){let n=e.trigger;switch(n.kind){case`manual`:return`When run manually`;case`webhook`:{let t=e.filters.filter(e=>e.path.trim());return t.length===0?`When a webhook is received`:`When a webhook is received where ${S(t.map(e=>`${e.path.trim()} = "${e.equals}"`))}`}default:return B(n,t)}}function H(e,t={}){let n=e.template.title.trim()||`Untitled task`,r=t.projectName?` in ${t.projectName}`:``,i=t.hostName?` on ${t.hostName}`:` on the project's default host`,a=t.profileName?` with profile ${t.profileName}`:``,o;switch(e.mode){case`continue`:{let t=e.groupingKey?.trim();o=t?`continue the task grouped by "${t}" (or create "${n}")`:`continue the matching task (or create "${n}")`;break}case`watch`:o=`create a watch task "${n}" that only raises attention when something relevant changed`;break;default:o=`create a fresh task "${n}"`}let s=[`${V(e,t)}, ${o}${r}${i}${a}`];if(s.push(e.overlap===`skip`?`skip if previous work is still open`:e.overlap===`queue_one`?`queue one occurrence if previous work is still open`:`append to the open task if previous work is still open`),(e.trigger.kind===`cron`||e.trigger.kind===`once`)&&s.push(e.missed===`skip`?`skip missed runs`:`run missed runs once on return`),e.continuation.enabled){let t=e.continuation;s.push(`continue automatically up to ${t.maxContinuations} times within ${t.maxElapsedMinutes} minutes`)}let c=e.completion.checks;return c&&c.length>0&&s.push(`run ${c.length===1?`1 check`:`${c.length} checks`}`),s.push(e.completion.requireHumanReview?`requires human review`:`no human review required`),T(s.join(`; `))}function U(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||`UTC`}catch{return`UTC`}}function W(e={}){return{name:``,enabled:!0,projectId:e.projectId??``,triggerKind:`manual`,onceAt:``,cronExpr:`0 9 * * 1-5`,cronTimezone:e.timezone??U(),dependencyTaskId:``,filters:[],title:``,objective:``,criteria:``,priority:2,hostId:``,profileId:``,mode:`fresh`,groupingKey:``,overlap:`skip`,missed:`skip`,continuationEnabled:!1,continuationObjective:``,maxContinuations:`5`,maxElapsedMinutes:`60`,maxTokens:``,maxCostUsd:``,checks:``,requireHumanReview:!0}}function G(e){if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?``:`${t.getFullYear()}-${C(t.getMonth()+1)}-${C(t.getDate())}T${C(t.getHours())}:${C(t.getMinutes())}`}function K(e){if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toISOString()}function ce(e,t={}){let n=W({projectId:e.projectId,timezone:t.timezone}),r=e.trigger,i=e.continuation;return{...n,name:e.name,enabled:e.enabled,triggerKind:r.kind,onceAt:r.kind===`once`?G(r.at):``,cronExpr:r.kind===`cron`?r.expr:n.cronExpr,cronTimezone:r.kind===`cron`?r.timezone:n.cronTimezone,dependencyTaskId:r.kind===`dependency`?r.taskId:``,filters:e.filters.map(e=>({...e})),title:e.template.title,objective:e.template.objective,criteria:e.template.acceptanceCriteria.join(`
3
+ `),priority:e.template.priority,hostId:e.hostId??``,profileId:e.profileId??``,mode:e.mode,groupingKey:e.groupingKey??``,overlap:e.overlap,missed:e.missed,continuationEnabled:i.enabled,continuationObjective:i.enabled?i.objective:``,maxContinuations:i.enabled?String(i.maxContinuations):n.maxContinuations,maxElapsedMinutes:i.enabled?String(i.maxElapsedMinutes):n.maxElapsedMinutes,maxTokens:i.enabled&&i.maxTokens!==null?String(i.maxTokens):``,maxCostUsd:i.enabled&&i.maxCostUsd!==null?String(i.maxCostUsd):``,checks:e.completion.checks?e.completion.checks.join(`
4
+ `):``,requireHumanReview:e.completion.requireHumanReview}}function q(e){return e.trim()===``?NaN:Number(e.trim())}function J(e){return e.trim()===``?null:Number(e.trim())}function Y(e){switch(e.triggerKind){case`manual`:return{kind:`manual`};case`once`:return{kind:`once`,at:K(e.onceAt)};case`cron`:return{kind:`cron`,expr:e.cronExpr.trim(),timezone:e.cronTimezone.trim()};case`webhook`:return{kind:`webhook`};case`dependency`:return{kind:`dependency`,taskId:e.dependencyTaskId}}}function X(e){let t=E(e.checks);return{name:e.name.trim(),enabled:e.enabled,projectId:e.projectId,trigger:Y(e),filters:e.filters.filter(e=>e.path.trim()||e.equals.trim()).map(e=>({path:e.path.trim(),equals:e.equals})),template:{title:e.title.trim(),objective:e.objective,acceptanceCriteria:E(e.criteria),priority:e.priority},hostId:e.hostId||null,profileId:e.profileId||null,mode:e.mode,groupingKey:e.groupingKey.trim()||null,overlap:e.overlap,missed:e.missed,continuation:e.continuationEnabled?{enabled:!0,objective:e.continuationObjective.trim(),maxContinuations:q(e.maxContinuations),maxElapsedMinutes:q(e.maxElapsedMinutes),maxTokens:J(e.maxTokens),maxCostUsd:J(e.maxCostUsd)}:{enabled:!1},completion:{checks:t.length>0?t:null,requireHumanReview:e.requireHumanReview}}}var le={name:`name`,enabled:`enabled`,projectId:`projectId`,trigger:`triggerKind`,"trigger.kind":`triggerKind`,"trigger.at":`onceAt`,"trigger.expr":`cronExpr`,"trigger.timezone":`cronTimezone`,"trigger.taskId":`dependencyTaskId`,"template.title":`title`,"template.objective":`objective`,"template.acceptanceCriteria":`criteria`,"template.priority":`priority`,hostId:`hostId`,profileId:`profileId`,mode:`mode`,groupingKey:`groupingKey`,overlap:`overlap`,missed:`missed`,"continuation.objective":`continuationObjective`,"continuation.maxContinuations":`maxContinuations`,"continuation.maxElapsedMinutes":`maxElapsedMinutes`,"continuation.maxTokens":`maxTokens`,"continuation.maxCostUsd":`maxCostUsd`,"completion.checks":`checks`,"completion.requireHumanReview":`requireHumanReview`};function Z(e){let t=e.map(String);if(t[0]===`filters`&&t.length>=3)return`filters.${Number(t[1])}.${t[2]===`equals`?`equals`:`path`}`;if(t[0]===`template`&&t[1]===`acceptanceCriteria`)return`criteria`;if(t[0]===`completion`&&t[1]===`checks`)return`checks`;for(let e=t.length;e>0;e--){let n=le[t.slice(0,e).join(`.`)];if(n)return n}return`form`}function Q(e,t,n,r){let i=q(e);return!Number.isInteger(i)||i<t||i>n?`${r} must be a whole number from ${t} to ${n}`:null}function ue(e){let t={},n=(e,n)=>{n&&!t[e]&&(t[e]=n)};switch(e.name.trim()||n(`name`,`Name is required`),e.projectId||n(`projectId`,`Choose a project`),e.title.trim()||n(`title`,`Task title is required`),e.triggerKind){case`once`:K(e.onceAt)||n(`onceAt`,`Choose a date and time`);break;case`cron`:n(`cronExpr`,M(e.cronExpr)),n(`cronTimezone`,se(e.cronTimezone));break;case`dependency`:e.dependencyTaskId||n(`dependencyTaskId`,`Choose the task to wait for`)}if(e.filters.forEach((e,t)=>{!e.path.trim()&&e.equals.trim()&&n(`filters.${t}.path`,`Enter a payload path`)}),e.mode===`continue`&&!e.groupingKey.trim()&&n(`groupingKey`,`A grouping key is required to continue an existing task`),e.continuationEnabled){if(e.continuationObjective.trim()||n(`continuationObjective`,`An objective is required when continuation is on`),n(`maxContinuations`,Q(e.maxContinuations,1,50,`Max continuations`)),n(`maxElapsedMinutes`,Q(e.maxElapsedMinutes,1,1440,`Max elapsed minutes`)),e.maxTokens.trim()){let t=q(e.maxTokens);(!Number.isInteger(t)||t<=0)&&n(`maxTokens`,`Max tokens must be a positive whole number`)}if(e.maxCostUsd.trim()){let t=q(e.maxCostUsd);(!Number.isFinite(t)||t<=0)&&n(`maxCostUsd`,`Max cost must be a positive amount`)}}let r=X(e),i=a.safeParse(r);if(!i.success)for(let e of i.error.issues)n(Z(e.path),e.message);return{input:i.success&&Object.keys(t).length===0?i.data:null,errors:t}}function $(e){return e.scheduledFor??e.createdAt}function de(...e){let t=new Map;for(let n of e)for(let e of n??[])t.set(e.id,e);return[...t.values()].sort((e,t)=>t.createdAt.localeCompare(e.createdAt)||$(t).localeCompare($(e)))}function fe(e){if(Array.isArray(e))return e;if(e&&typeof e==`object`){let t=e;if(Array.isArray(t.items))return t.items;if(Array.isArray(t.occurrences))return t.occurrences}return[]}function pe(e,t){return`curl -X POST -H 'Authorization: Bearer ${e}' -H 'Content-Type: application/json' -d '{}' ${t}`}export{m as C,ee as D,te as E,re as O,ue as S,g as T,b as _,ie as a,H as b,B as c,W as d,Z as f,de as g,U as h,x as i,ne as k,ce as l,K as m,v as n,pe as o,z as p,y as r,L as s,ae as t,X as u,fe as v,h as w,M as x,$ as y};
5
+ //# sourceMappingURL=describe-D6KLGKWa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe-D6KLGKWa.js","names":["useMemo","useState","useCallback","__toESM","require_react","require_jsx_runtime","create","apiPatch","AutomationInput","TriangleAlert","apiPost","errorMessage","useSyncStore","CircleCheck","toast","import_react","import_jsx_runtime","FailureCount","count","automationPath","id","suffix","useLocalAutomations","set","s","a","byId","list","newer","b","useMergedAutomations","store","local","deleted","out","useMergedAutomation","fromStore","fromLocal","useToggleEnabled","busy","setBusy","res","enabled","e","useRunNow","state","onDone","TRIGGER_KIND_LABELS","MODE_OPTIONS","OVERLAP_OPTIONS","MISSED_OPTIONS","modeLabel","m","mode","TEMPLATE_VARIABLES","listText","items","pad","n","ordinal","mod100","capitalize","lines","text","l","DAY_NAMES","MONTH_NAMES","CRON_FIELDS","d","parseValue","lower","token","def","idx","parseCronField","src","parts","values","step","part","base","stepStr","extra","every","start","end","av","bv","v","i","sorted","full","parseCron","trimmed","expr","fields","parsed","validateCron","validateTimezone","tz","isContiguous","describeTime","h","at","times","hv","mv","first","last","mm","mondayFirst","describeDays","dom","dow","months","mon","inMonths","days","key","names","ords","of","describeCron","f","time","timezone","describeCronOrRaw","formatAbsolute","iso","describeTrigger","fmt","ctx","trigger","title","triggerClause","t","input","filters","summarizeAutomation","project","host","profile","action","c","checks","localTimezone","emptyDraft","opts","isoToLocalInput","localInputToIso","value","draftFromAutomation","toNumber","toOptionalNumber","draftTrigger","draftToInput","PATH_TO_FIELD","fieldForPath","path","intError","min","max","label","validateDraft","errors","msg","raw","issue","occurrenceTime","o","mergeOccurrences","lists","normalizeHistory","r","curlExample","url"],"sources":["../../src/features/automations/controls.tsx","../../src/features/automations/describe.ts"],"sourcesContent":["import type { Automation } from \"@switchyard/protocol\";\nimport { CircleCheck, TriangleAlert } from \"lucide-react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { create } from \"zustand\";\nimport { toast } from \"../../components/ui/Toast\";\nimport { apiPatch, apiPost, errorMessage } from \"../../sync/api\";\nimport { useSyncStore } from \"../../sync/store\";\n\n/* Small building blocks shared by the Automations list and editor. */\n\n/** Failure count as icon + text; warning tone when > 0. */\nexport function FailureCount({ count }: { count: number }) {\n if (count > 0) {\n return (\n <span className=\"inline-flex items-center gap-1 text-sm text-warning\">\n <TriangleAlert aria-hidden className=\"size-4 shrink-0\" />\n {count === 1 ? \"1 failure\" : `${count} failures`}\n </span>\n );\n }\n return (\n <span className=\"inline-flex items-center gap-1 text-sm text-muted\">\n <CircleCheck aria-hidden className=\"size-4 shrink-0\" />\n No failures\n </span>\n );\n}\n\nexport const automationPath = (id: string, suffix = \"\") =>\n `/api/automations/${encodeURIComponent(id)}${suffix}`;\n\n/* ------------------------------------------------------------------ */\n/* Automations acknowledged over REST (create/patch responses, list */\n/* fallback) so views do not wait for the automation.updated event. */\n/* ------------------------------------------------------------------ */\n\ninterface LocalAutomations {\n byId: Record<string, Automation>;\n deleted: Record<string, true>;\n put(a: Automation): void;\n putMany(list: Automation[]): void;\n remove(id: string): void;\n}\n\nexport const useLocalAutomations = create<LocalAutomations>()((set) => ({\n byId: {},\n deleted: {},\n put: (a) => set((s) => ({ byId: { ...s.byId, [a.id]: a } })),\n putMany: (list) =>\n set((s) => {\n const byId = { ...s.byId };\n for (const a of list) byId[a.id] = a;\n return { byId };\n }),\n remove: (id) =>\n set((s) => {\n const byId = { ...s.byId };\n delete byId[id];\n return { byId, deleted: { ...s.deleted, [id]: true } };\n }),\n}));\n\nfunction newer(a: Automation | undefined, b: Automation | undefined): Automation | undefined {\n if (!a) return b;\n if (!b) return a;\n return b.updatedAt > a.updatedAt ? b : a;\n}\n\n/** Store automations merged with REST acknowledgements (newest updatedAt wins). */\nexport function useMergedAutomations(): Record<string, Automation> {\n const store = useSyncStore((s) => s.automations);\n const local = useLocalAutomations((s) => s.byId);\n const deleted = useLocalAutomations((s) => s.deleted);\n return useMemo(() => {\n const out: Record<string, Automation> = {};\n for (const id of new Set([...Object.keys(store), ...Object.keys(local)])) {\n if (deleted[id]) continue;\n const a = newer(store[id], local[id]);\n if (a) out[id] = a;\n }\n return out;\n }, [store, local, deleted]);\n}\n\nexport function useMergedAutomation(id: string | undefined): Automation | undefined {\n const fromStore = useSyncStore((s) => (id ? s.automations[id] : undefined));\n const fromLocal = useLocalAutomations((s) => (id ? s.byId[id] : undefined));\n const deleted = useLocalAutomations((s) => (id ? s.deleted[id] : undefined));\n return deleted ? undefined : newer(fromStore, fromLocal);\n}\n\n/** Enable/disable with no optimistic success: busy until the coordinator acknowledges. */\nexport function useToggleEnabled() {\n const [busy, setBusy] = useState<Record<string, boolean>>({});\n const toggle = useCallback(async (a: Pick<Automation, \"id\" | \"name\">, enabled: boolean) => {\n setBusy((b) => ({ ...b, [a.id]: true }));\n try {\n const res = await apiPatch<Automation | undefined>(automationPath(a.id), { enabled });\n if (res && typeof res === \"object\" && \"id\" in res) useLocalAutomations.getState().put(res);\n toast.success(`${a.name} ${enabled ? \"enabled\" : \"disabled\"}`);\n } catch (e) {\n toast.error(`Could not ${enabled ? \"enable\" : \"disable\"} ${a.name}: ${errorMessage(e)}`);\n } finally {\n setBusy((b) => ({ ...b, [a.id]: false }));\n }\n }, []);\n return { busy, toggle };\n}\n\n/** Manual \"Run now\": busy until acknowledged; never reports success early. */\nexport function useRunNow(onDone?: () => void) {\n const [busy, setBusy] = useState<Record<string, boolean>>({});\n const run = useCallback(\n async (a: Pick<Automation, \"id\" | \"name\">) => {\n setBusy((b) => ({ ...b, [a.id]: true }));\n try {\n const res = await apiPost<{ state?: string } | undefined>(automationPath(a.id, \"/run\"));\n const state = res && typeof res === \"object\" ? res.state : undefined;\n toast.success(\n state && state !== \"fired\"\n ? `${a.name}: occurrence recorded (${state.replace(/_/g, \" \")})`\n : `${a.name} started`,\n );\n onDone?.();\n } catch (e) {\n toast.error(`Could not run ${a.name}: ${errorMessage(e)}`);\n } finally {\n setBusy((b) => ({ ...b, [a.id]: false }));\n }\n },\n [onDone],\n );\n return { busy, run };\n}\n","import {\n type Automation,\n AutomationInput,\n type Occurrence,\n PRIORITY_LABELS,\n type Priority,\n type Trigger,\n} from \"@switchyard/protocol\";\n\n/*\n * Pure helpers for the Automations feature: a small cron describer, trigger\n * and whole-automation summaries, the editor draft <-> AutomationInput\n * conversion with field-level validation, and history merging.\n */\n\n/* ------------------------------------------------------------------ */\n/* Labels and explanations */\n/* ------------------------------------------------------------------ */\n\nexport type AutomationMode = AutomationInput[\"mode\"];\nexport type OverlapPolicy = AutomationInput[\"overlap\"];\nexport type MissedPolicy = AutomationInput[\"missed\"];\nexport type TriggerKind = Trigger[\"kind\"];\n\nexport const TRIGGER_KIND_LABELS: Record<TriggerKind, string> = {\n manual: \"Manual\",\n once: \"Once\",\n cron: \"Schedule\",\n webhook: \"Webhook\",\n dependency: \"Dependency\",\n};\n\nexport const MODE_OPTIONS: { value: AutomationMode; label: string; explanation: string }[] = [\n { value: \"fresh\", label: \"Fresh\", explanation: \"Fresh: a new task per occurrence\" },\n {\n value: \"continue\",\n label: \"Continue\",\n explanation: \"Continue: reuse the task with the same grouping key\",\n },\n {\n value: \"watch\",\n label: \"Watch\",\n explanation: \"Watch: only raises attention when something relevant changed\",\n },\n];\n\nexport const OVERLAP_OPTIONS: { value: OverlapPolicy; label: string; explanation: string }[] = [\n {\n value: \"skip\",\n label: \"Skip\",\n explanation: \"Skip: drop the occurrence while earlier work is still open\",\n },\n {\n value: \"queue_one\",\n label: \"Queue one\",\n explanation: \"Queue one: keep a single pending occurrence and fire it when the open work ends\",\n },\n {\n value: \"append\",\n label: \"Append\",\n explanation: \"Append: add the new objective to the open task (as a follow-up if it is running)\",\n },\n];\n\nexport const MISSED_OPTIONS: { value: MissedPolicy; label: string; explanation: string }[] = [\n {\n value: \"skip\",\n label: \"Skip\",\n explanation: \"Skip: occurrences missed while the coordinator was down are recorded and skipped\",\n },\n {\n value: \"run_once\",\n label: \"Run once\",\n explanation: \"Run once: on return, fire the newest missed occurrence once\",\n },\n];\n\nexport function modeLabel(mode: AutomationMode): string {\n return MODE_OPTIONS.find((m) => m.value === mode)?.label ?? mode;\n}\n\nexport function priorityLabel(p: Priority): string {\n return PRIORITY_LABELS[p] ?? String(p);\n}\n\nexport const TEMPLATE_VARIABLES = [\"{{date}}\", \"{{time}}\", \"{{occurrence}}\", \"{{payload.<path>}}\"];\n\n/* ------------------------------------------------------------------ */\n/* Text utilities */\n/* ------------------------------------------------------------------ */\n\n/** \"a\", \"a and b\", \"a, b and c\". */\nexport function listText(items: string[]): string {\n if (items.length <= 1) return items[0] ?? \"\";\n return `${items.slice(0, -1).join(\", \")} and ${items[items.length - 1]}`;\n}\n\nfunction pad(n: number): string {\n return String(n).padStart(2, \"0\");\n}\n\nexport function ordinal(n: number): string {\n const mod100 = n % 100;\n if (mod100 >= 11 && mod100 <= 13) return `${n}th`;\n switch (n % 10) {\n case 1:\n return `${n}st`;\n case 2:\n return `${n}nd`;\n case 3:\n return `${n}rd`;\n default:\n return `${n}th`;\n }\n}\n\nfunction capitalize(s: string): string {\n return s ? s[0]!.toUpperCase() + s.slice(1) : s;\n}\n\n/** Non-empty trimmed lines. */\nexport function lines(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n}\n\n/* ------------------------------------------------------------------ */\n/* Cron */\n/* ------------------------------------------------------------------ */\n\nconst DAY_NAMES = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nconst MONTH_NAMES = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\",\n];\n\ninterface FieldDef {\n name: string;\n min: number;\n max: number;\n /** Three-letter aliases mapped to `min + index`. */\n names?: string[];\n}\n\nconst CRON_FIELDS: FieldDef[] = [\n { name: \"Minute\", min: 0, max: 59 },\n { name: \"Hour\", min: 0, max: 23 },\n { name: \"Day of month\", min: 1, max: 31 },\n {\n name: \"Month\",\n min: 1,\n max: 12,\n names: MONTH_NAMES.map((m) => m.slice(0, 3).toLowerCase()),\n },\n {\n name: \"Day of week\",\n min: 0,\n max: 7,\n names: DAY_NAMES.map((d) => d.slice(0, 3).toLowerCase()),\n },\n];\n\nexport interface CronField {\n /** `*` (or `?`): every value. */\n any: boolean;\n /** Expanded, sorted, unique values (empty when `any`). */\n values: number[];\n /** Set when the field is a single `*\\/n` or `a/n` step. */\n step: { every: number; start: number } | null;\n /** Uses croner extensions (L, W, #) the describer does not explain. */\n extended: boolean;\n}\n\nfunction parseValue(token: string, def: FieldDef): number | string {\n const lower = token.toLowerCase();\n if (def.names) {\n const idx = def.names.indexOf(lower);\n if (idx >= 0) return def.min + idx;\n }\n if (!/^\\d+$/.test(token)) return `\"${token}\" is not a number`;\n const n = Number(token);\n if (n < def.min || n > def.max) return `${n} is out of range ${def.min}–${def.max}`;\n return n;\n}\n\n/** Parse one cron field; returns an error message for invalid input. */\nexport function parseCronField(src: string, def: FieldDef): CronField | string {\n if (src === \"*\" || src === \"?\") return { any: true, values: [], step: null, extended: false };\n if (/[LW#]/i.test(src) && !def.names?.some((n) => src.toLowerCase().includes(n))) {\n if (!/^[0-9A-Za-z*?,\\-/#]+$/.test(src)) return `\"${src}\" is not valid`;\n return { any: false, values: [], step: null, extended: true };\n }\n const parts = src.split(\",\");\n const values = new Set<number>();\n let step: CronField[\"step\"] = null;\n for (const part of parts) {\n if (!part) return \"empty list item\";\n const [base, stepStr, extra] = part.split(\"/\");\n if (extra !== undefined) return `\"${part}\" has more than one step`;\n let every = 1;\n if (stepStr !== undefined) {\n if (!/^\\d+$/.test(stepStr) || Number(stepStr) < 1) return `\"${stepStr}\" is not a valid step`;\n every = Number(stepStr);\n }\n let start: number;\n let end: number;\n if (base === \"*\" || base === \"?\") {\n start = def.min;\n end = def.max;\n } else if (base?.includes(\"-\")) {\n const [a, b] = base.split(\"-\");\n const av = parseValue(a ?? \"\", def);\n const bv = parseValue(b ?? \"\", def);\n if (typeof av === \"string\") return av;\n if (typeof bv === \"string\") return bv;\n if (av > bv) return `range ${base} runs backwards`;\n start = av;\n end = bv;\n } else {\n const v = parseValue(base ?? \"\", def);\n if (typeof v === \"string\") return v;\n start = v;\n end = stepStr !== undefined ? def.max : v;\n }\n for (let i = start; i <= end; i += every) values.add(i);\n if (parts.length === 1 && stepStr !== undefined && !base?.includes(\"-\")) {\n step = { every, start };\n }\n }\n let sorted = [...values].sort((a, b) => a - b);\n // Day of week: 7 is Sunday.\n if (def.max === 7) sorted = [...new Set(sorted.map((v) => v % 7))].sort((a, b) => a - b);\n const full = def.max === 7 ? 7 : def.max - def.min + 1;\n if (sorted.length === full && !step)\n return { any: true, values: [], step: null, extended: false };\n return { any: false, values: sorted, step, extended: false };\n}\n\nexport function parseCron(expr: string): CronField[] | string {\n const trimmed = expr.trim();\n if (!trimmed) return \"Enter a cron expression\";\n const fields = trimmed.split(/\\s+/);\n if (fields.length !== 5) {\n return `Expected 5 fields (minute hour day-of-month month day-of-week), got ${fields.length}`;\n }\n const out: CronField[] = [];\n for (let i = 0; i < 5; i++) {\n const def = CRON_FIELDS[i]!;\n const parsed = parseCronField(fields[i]!, def);\n if (typeof parsed === \"string\") return `${def.name}: ${parsed}`;\n out.push(parsed);\n }\n return out;\n}\n\n/** Null when valid, otherwise a message. */\nexport function validateCron(expr: string): string | null {\n const parsed = parseCron(expr);\n return typeof parsed === \"string\" ? parsed : null;\n}\n\n/** Null when the IANA timezone is known to this browser. */\nexport function validateTimezone(tz: string): string | null {\n if (!tz.trim()) return \"Enter a timezone\";\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: tz.trim() });\n return null;\n } catch {\n return `Unknown timezone \"${tz}\"`;\n }\n}\n\nfunction isContiguous(values: number[]): boolean {\n for (let i = 1; i < values.length; i++) if (values[i] !== values[i - 1]! + 1) return false;\n return values.length > 0;\n}\n\ntype TimePhrase = { kind: \"at\"; text: string } | { kind: \"freq\"; text: string };\n\nfunction describeTime(m: CronField, h: CronField): TimePhrase | null {\n if (m.any && h.any) return { kind: \"freq\", text: \"Every minute\" };\n if (m.step && m.step.start === 0 && h.any) {\n return {\n kind: \"freq\",\n text: m.step.every === 1 ? \"Every minute\" : `Every ${m.step.every} minutes`,\n };\n }\n if (m.any) {\n if (h.step || h.values.length === 0) return null;\n if (isContiguous(h.values)) {\n return {\n kind: \"freq\",\n text: `Every minute from ${pad(h.values[0]!)}:00 to ${pad(h.values[h.values.length - 1]!)}:59`,\n };\n }\n return null;\n }\n if (h.any) {\n if (m.step) return null;\n if (m.values.length === 1 && m.values[0] === 0) return { kind: \"freq\", text: \"Every hour\" };\n return {\n kind: \"freq\",\n text: `Every hour at ${listText(m.values.map((v) => `:${pad(v)}`))}`,\n };\n }\n if (h.step && h.step.start === 0 && m.values.length === 1 && !m.step) {\n const at = m.values[0] === 0 ? \"\" : ` at :${pad(m.values[0]!)}`;\n return {\n kind: \"freq\",\n text: h.step.every === 1 ? `Every hour${at}` : `Every ${h.step.every} hours${at}`,\n };\n }\n if (m.values.length * h.values.length <= 6) {\n const times: string[] = [];\n for (const hv of h.values) for (const mv of m.values) times.push(`${pad(hv)}:${pad(mv)}`);\n return { kind: \"at\", text: listText(times) };\n }\n if (!isContiguous(h.values)) return null;\n const first = h.values[0]!;\n const last = h.values[h.values.length - 1]!;\n if (m.step && m.step.start === 0) {\n return {\n kind: \"freq\",\n text: `Every ${m.step.every} minutes from ${pad(first)}:00 to ${pad(last)}:59`,\n };\n }\n if (m.values.length === 1) {\n const mm = pad(m.values[0]!);\n return { kind: \"freq\", text: `Every hour from ${pad(first)}:${mm} to ${pad(last)}:${mm}` };\n }\n return null;\n}\n\n/** Monday-first ordering for day-of-week lists. */\nfunction mondayFirst(a: number, b: number): number {\n return ((a + 6) % 7) - ((b + 6) % 7);\n}\n\nfunction describeDays(\n dom: CronField,\n mon: CronField,\n dow: CronField,\n): { lead: string; qual: string } | null {\n if (!dom.any && !dow.any) return null;\n const months = mon.any ? null : listText(mon.values.map((v) => MONTH_NAMES[v - 1]!));\n const inMonths = months ? ` in ${months}` : \"\";\n if (!dow.any) {\n const days = [...dow.values].sort(mondayFirst);\n const key = days.join(\",\");\n if (key === \"1,2,3,4,5\") {\n return { lead: `Every weekday${inMonths}`, qual: ` on weekdays${inMonths}` };\n }\n if (key === \"6,0\") {\n return { lead: `Every Saturday and Sunday${inMonths}`, qual: ` on weekends${inMonths}` };\n }\n const names = days.map((d) => DAY_NAMES[d]!);\n return {\n lead: `Every ${listText(names)}${inMonths}`,\n qual: ` on ${listText(names.map((n) => `${n}s`))}${inMonths}`,\n };\n }\n if (!dom.any) {\n if (dom.values.length > 5) return null;\n const ords = listText(dom.values.map(ordinal));\n const of = months ? months : \"every month\";\n return { lead: `On the ${ords} of ${of}`, qual: ` on the ${ords} of ${of}` };\n }\n return { lead: `Every day${inMonths}`, qual: inMonths };\n}\n\n/**\n * Human description of a 5-field cron expression (\"Every weekday at 09:00\n * (America/Denver)\"), or null when the expression is outside what this small\n * describer covers.\n */\nexport function describeCron(expr: string, timezone?: string): string | null {\n const parsed = parseCron(expr);\n if (typeof parsed === \"string\") return null;\n if (parsed.some((f) => f.extended)) return null;\n const [m, h, dom, mon, dow] = parsed as [CronField, CronField, CronField, CronField, CronField];\n const time = describeTime(m, h);\n const days = describeDays(dom, mon, dow);\n if (!time || !days) return null;\n const text = time.kind === \"at\" ? `${days.lead} at ${time.text}` : `${time.text}${days.qual}`;\n return timezone ? `${text} (${timezone})` : text;\n}\n\n/** describeCron with the raw-expression fallback. */\nexport function describeCronOrRaw(expr: string, timezone: string): string {\n return describeCron(expr, timezone) ?? `Cron ${expr.trim()} (${timezone})`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Summaries */\n/* ------------------------------------------------------------------ */\n\nexport function formatAbsolute(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return d.toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" });\n}\n\nexport interface SummaryContext {\n projectName?: string | null;\n /** Name of the explicitly selected host; null/undefined means the project default. */\n hostName?: string | null;\n profileName?: string | null;\n taskTitle?: (taskId: string) => string | undefined;\n formatDate?: (iso: string) => string;\n}\n\n/** Short trigger summary for list rows. */\nexport function describeTrigger(trigger: Trigger, ctx: SummaryContext = {}): string {\n const fmt = ctx.formatDate ?? formatAbsolute;\n switch (trigger.kind) {\n case \"manual\":\n return \"Manual\";\n case \"once\":\n return trigger.at && !Number.isNaN(Date.parse(trigger.at))\n ? `Once at ${fmt(trigger.at)}`\n : \"Once (no time chosen)\";\n case \"cron\":\n return describeCronOrRaw(trigger.expr, trigger.timezone);\n case \"webhook\":\n return \"Webhook\";\n case \"dependency\": {\n const title = trigger.taskId ? ctx.taskTitle?.(trigger.taskId) : undefined;\n if (title) return `When \"${title}\" is done`;\n return trigger.taskId ? \"When a deleted task is done\" : \"When a task is done\";\n }\n }\n}\n\ntype SummaryInput = Pick<\n AutomationInput,\n | \"trigger\"\n | \"filters\"\n | \"template\"\n | \"mode\"\n | \"groupingKey\"\n | \"overlap\"\n | \"missed\"\n | \"continuation\"\n | \"completion\"\n>;\n\nfunction triggerClause(input: SummaryInput, ctx: SummaryContext): string {\n const t = input.trigger;\n switch (t.kind) {\n case \"manual\":\n return \"When run manually\";\n case \"webhook\": {\n const filters = input.filters.filter((f) => f.path.trim());\n if (filters.length === 0) return \"When a webhook is received\";\n return `When a webhook is received where ${listText(\n filters.map((f) => `${f.path.trim()} = \"${f.equals}\"`),\n )}`;\n }\n default:\n return describeTrigger(t, ctx);\n }\n}\n\n/**\n * One-paragraph description of what the automation does, e.g. 'Every weekday\n * at 09:00 (America/Denver), create a fresh task \"Triage\" in Web on my-server; skip\n * if previous work is still open; skip missed runs; requires human review'.\n */\nexport function summarizeAutomation(input: SummaryInput, ctx: SummaryContext = {}): string {\n const title = input.template.title.trim() || \"Untitled task\";\n const project = ctx.projectName ? ` in ${ctx.projectName}` : \"\";\n const host = ctx.hostName ? ` on ${ctx.hostName}` : \" on the project's default host\";\n const profile = ctx.profileName ? ` with profile ${ctx.profileName}` : \"\";\n let action: string;\n switch (input.mode) {\n case \"continue\": {\n const key = input.groupingKey?.trim();\n action = key\n ? `continue the task grouped by \"${key}\" (or create \"${title}\")`\n : `continue the matching task (or create \"${title}\")`;\n break;\n }\n case \"watch\":\n action = `create a watch task \"${title}\" that only raises attention when something relevant changed`;\n break;\n default:\n action = `create a fresh task \"${title}\"`;\n }\n const parts = [`${triggerClause(input, ctx)}, ${action}${project}${host}${profile}`];\n parts.push(\n input.overlap === \"skip\"\n ? \"skip if previous work is still open\"\n : input.overlap === \"queue_one\"\n ? \"queue one occurrence if previous work is still open\"\n : \"append to the open task if previous work is still open\",\n );\n if (input.trigger.kind === \"cron\" || input.trigger.kind === \"once\") {\n parts.push(input.missed === \"skip\" ? \"skip missed runs\" : \"run missed runs once on return\");\n }\n if (input.continuation.enabled) {\n const c = input.continuation;\n parts.push(\n `continue automatically up to ${c.maxContinuations} times within ${c.maxElapsedMinutes} minutes`,\n );\n }\n const checks = input.completion.checks;\n if (checks && checks.length > 0) {\n parts.push(`run ${checks.length === 1 ? \"1 check\" : `${checks.length} checks`}`);\n }\n parts.push(\n input.completion.requireHumanReview ? \"requires human review\" : \"no human review required\",\n );\n return capitalize(parts.join(\"; \"));\n}\n\n/* ------------------------------------------------------------------ */\n/* Editor draft */\n/* ------------------------------------------------------------------ */\n\n/** Form state: strings for inputs so partial edits survive validation. */\nexport interface AutomationDraft {\n name: string;\n enabled: boolean;\n projectId: string;\n triggerKind: TriggerKind;\n /** datetime-local value (local time, no zone). */\n onceAt: string;\n cronExpr: string;\n cronTimezone: string;\n dependencyTaskId: string;\n filters: { path: string; equals: string }[];\n title: string;\n objective: string;\n /** One criterion per line. */\n criteria: string;\n priority: Priority;\n /** \"\" = project default. */\n hostId: string;\n /** \"\" = project default. */\n profileId: string;\n mode: AutomationMode;\n groupingKey: string;\n overlap: OverlapPolicy;\n missed: MissedPolicy;\n continuationEnabled: boolean;\n continuationObjective: string;\n maxContinuations: string;\n maxElapsedMinutes: string;\n maxTokens: string;\n maxCostUsd: string;\n /** One check per line; empty = project default (null). */\n checks: string;\n requireHumanReview: boolean;\n}\n\nexport function localTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n } catch {\n return \"UTC\";\n }\n}\n\nexport function emptyDraft(opts: { projectId?: string; timezone?: string } = {}): AutomationDraft {\n return {\n name: \"\",\n enabled: true,\n projectId: opts.projectId ?? \"\",\n triggerKind: \"manual\",\n onceAt: \"\",\n cronExpr: \"0 9 * * 1-5\",\n cronTimezone: opts.timezone ?? localTimezone(),\n dependencyTaskId: \"\",\n filters: [],\n title: \"\",\n objective: \"\",\n criteria: \"\",\n priority: 2,\n hostId: \"\",\n profileId: \"\",\n mode: \"fresh\",\n groupingKey: \"\",\n overlap: \"skip\",\n missed: \"skip\",\n continuationEnabled: false,\n continuationObjective: \"\",\n maxContinuations: \"5\",\n maxElapsedMinutes: \"60\",\n maxTokens: \"\",\n maxCostUsd: \"\",\n checks: \"\",\n requireHumanReview: true,\n };\n}\n\n/** ISO -> datetime-local value in this browser's timezone. */\nexport function isoToLocalInput(iso: string | null | undefined): string {\n if (!iso) return \"\";\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return \"\";\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** datetime-local value -> ISO (interpreted as local time), or \"\" when empty/invalid. */\nexport function localInputToIso(value: string): string {\n if (!value) return \"\";\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? \"\" : d.toISOString();\n}\n\nexport function draftFromAutomation(\n a: Automation | AutomationInput,\n opts: { timezone?: string } = {},\n): AutomationDraft {\n const base = emptyDraft({ projectId: a.projectId, timezone: opts.timezone });\n const t = a.trigger;\n const c = a.continuation;\n return {\n ...base,\n name: a.name,\n enabled: a.enabled,\n triggerKind: t.kind,\n onceAt: t.kind === \"once\" ? isoToLocalInput(t.at) : \"\",\n cronExpr: t.kind === \"cron\" ? t.expr : base.cronExpr,\n cronTimezone: t.kind === \"cron\" ? t.timezone : base.cronTimezone,\n dependencyTaskId: t.kind === \"dependency\" ? t.taskId : \"\",\n filters: a.filters.map((f) => ({ ...f })),\n title: a.template.title,\n objective: a.template.objective,\n criteria: a.template.acceptanceCriteria.join(\"\\n\"),\n priority: a.template.priority,\n hostId: a.hostId ?? \"\",\n profileId: a.profileId ?? \"\",\n mode: a.mode,\n groupingKey: a.groupingKey ?? \"\",\n overlap: a.overlap,\n missed: a.missed,\n continuationEnabled: c.enabled,\n continuationObjective: c.enabled ? c.objective : \"\",\n maxContinuations: c.enabled ? String(c.maxContinuations) : base.maxContinuations,\n maxElapsedMinutes: c.enabled ? String(c.maxElapsedMinutes) : base.maxElapsedMinutes,\n maxTokens: c.enabled && c.maxTokens !== null ? String(c.maxTokens) : \"\",\n maxCostUsd: c.enabled && c.maxCostUsd !== null ? String(c.maxCostUsd) : \"\",\n checks: a.completion.checks ? a.completion.checks.join(\"\\n\") : \"\",\n requireHumanReview: a.completion.requireHumanReview,\n };\n}\n\nfunction toNumber(s: string): number {\n return s.trim() === \"\" ? Number.NaN : Number(s.trim());\n}\n\nfunction toOptionalNumber(s: string): number | null {\n return s.trim() === \"\" ? null : Number(s.trim());\n}\n\nfunction draftTrigger(d: AutomationDraft): Trigger {\n switch (d.triggerKind) {\n case \"manual\":\n return { kind: \"manual\" };\n case \"once\":\n return { kind: \"once\", at: localInputToIso(d.onceAt) };\n case \"cron\":\n return { kind: \"cron\", expr: d.cronExpr.trim(), timezone: d.cronTimezone.trim() };\n case \"webhook\":\n return { kind: \"webhook\" };\n case \"dependency\":\n return { kind: \"dependency\", taskId: d.dependencyTaskId };\n }\n}\n\n/**\n * Build the request body from a draft. The result is shaped like an\n * AutomationInput but is not validated (numbers may be NaN, strings empty);\n * run validateDraft before sending it.\n */\nexport function draftToInput(d: AutomationDraft): AutomationInput {\n const checks = lines(d.checks);\n return {\n name: d.name.trim(),\n enabled: d.enabled,\n projectId: d.projectId,\n trigger: draftTrigger(d),\n filters: d.filters\n .filter((f) => f.path.trim() || f.equals.trim())\n .map((f) => ({ path: f.path.trim(), equals: f.equals })),\n template: {\n title: d.title.trim(),\n objective: d.objective,\n acceptanceCriteria: lines(d.criteria),\n priority: d.priority,\n },\n hostId: d.hostId || null,\n profileId: d.profileId || null,\n mode: d.mode,\n groupingKey: d.groupingKey.trim() || null,\n overlap: d.overlap,\n missed: d.missed,\n continuation: d.continuationEnabled\n ? {\n enabled: true,\n objective: d.continuationObjective.trim(),\n maxContinuations: toNumber(d.maxContinuations),\n maxElapsedMinutes: toNumber(d.maxElapsedMinutes),\n maxTokens: toOptionalNumber(d.maxTokens),\n maxCostUsd: toOptionalNumber(d.maxCostUsd),\n }\n : { enabled: false },\n completion: {\n checks: checks.length > 0 ? checks : null,\n requireHumanReview: d.requireHumanReview,\n },\n };\n}\n\n/** Draft field keys that can carry an inline error. */\nexport type DraftField =\n | keyof AutomationDraft\n | `filters.${number}.path`\n | `filters.${number}.equals`\n | \"form\";\n\nexport type DraftErrors = Partial<Record<DraftField, string>>;\n\nconst PATH_TO_FIELD: Record<string, DraftField> = {\n name: \"name\",\n enabled: \"enabled\",\n projectId: \"projectId\",\n trigger: \"triggerKind\",\n \"trigger.kind\": \"triggerKind\",\n \"trigger.at\": \"onceAt\",\n \"trigger.expr\": \"cronExpr\",\n \"trigger.timezone\": \"cronTimezone\",\n \"trigger.taskId\": \"dependencyTaskId\",\n \"template.title\": \"title\",\n \"template.objective\": \"objective\",\n \"template.acceptanceCriteria\": \"criteria\",\n \"template.priority\": \"priority\",\n hostId: \"hostId\",\n profileId: \"profileId\",\n mode: \"mode\",\n groupingKey: \"groupingKey\",\n overlap: \"overlap\",\n missed: \"missed\",\n \"continuation.objective\": \"continuationObjective\",\n \"continuation.maxContinuations\": \"maxContinuations\",\n \"continuation.maxElapsedMinutes\": \"maxElapsedMinutes\",\n \"continuation.maxTokens\": \"maxTokens\",\n \"continuation.maxCostUsd\": \"maxCostUsd\",\n \"completion.checks\": \"checks\",\n \"completion.requireHumanReview\": \"requireHumanReview\",\n};\n\n/** Map a zod issue path to a draft field. */\nexport function fieldForPath(path: readonly PropertyKey[]): DraftField {\n const parts = path.map(String);\n if (parts[0] === \"filters\" && parts.length >= 3) {\n return `filters.${Number(parts[1])}.${parts[2] === \"equals\" ? \"equals\" : \"path\"}`;\n }\n if (parts[0] === \"template\" && parts[1] === \"acceptanceCriteria\") return \"criteria\";\n if (parts[0] === \"completion\" && parts[1] === \"checks\") return \"checks\";\n for (let n = parts.length; n > 0; n--) {\n const f = PATH_TO_FIELD[parts.slice(0, n).join(\".\")];\n if (f) return f;\n }\n return \"form\";\n}\n\nfunction intError(s: string, min: number, max: number, label: string): string | null {\n const n = toNumber(s);\n if (!Number.isInteger(n) || n < min || n > max) {\n return `${label} must be a whole number from ${min} to ${max}`;\n }\n return null;\n}\n\n/**\n * Validate a draft: friendly checks first (required fields, cron, timezone,\n * number ranges), then AutomationInput.safeParse for anything else.\n */\nexport function validateDraft(d: AutomationDraft): {\n input: AutomationInput | null;\n errors: DraftErrors;\n} {\n const errors: DraftErrors = {};\n const set = (f: DraftField, msg: string | null) => {\n if (msg && !errors[f]) errors[f] = msg;\n };\n if (!d.name.trim()) set(\"name\", \"Name is required\");\n if (!d.projectId) set(\"projectId\", \"Choose a project\");\n if (!d.title.trim()) set(\"title\", \"Task title is required\");\n switch (d.triggerKind) {\n case \"once\":\n if (!localInputToIso(d.onceAt)) set(\"onceAt\", \"Choose a date and time\");\n break;\n case \"cron\":\n set(\"cronExpr\", validateCron(d.cronExpr));\n set(\"cronTimezone\", validateTimezone(d.cronTimezone));\n break;\n case \"dependency\":\n if (!d.dependencyTaskId) set(\"dependencyTaskId\", \"Choose the task to wait for\");\n break;\n }\n d.filters.forEach((f, i) => {\n if (!f.path.trim() && f.equals.trim()) set(`filters.${i}.path`, \"Enter a payload path\");\n });\n if (d.mode === \"continue\" && !d.groupingKey.trim()) {\n set(\"groupingKey\", \"A grouping key is required to continue an existing task\");\n }\n if (d.continuationEnabled) {\n if (!d.continuationObjective.trim()) {\n set(\"continuationObjective\", \"An objective is required when continuation is on\");\n }\n set(\"maxContinuations\", intError(d.maxContinuations, 1, 50, \"Max continuations\"));\n set(\"maxElapsedMinutes\", intError(d.maxElapsedMinutes, 1, 1440, \"Max elapsed minutes\"));\n if (d.maxTokens.trim()) {\n const n = toNumber(d.maxTokens);\n if (!Number.isInteger(n) || n <= 0)\n set(\"maxTokens\", \"Max tokens must be a positive whole number\");\n }\n if (d.maxCostUsd.trim()) {\n const n = toNumber(d.maxCostUsd);\n if (!Number.isFinite(n) || n <= 0) set(\"maxCostUsd\", \"Max cost must be a positive amount\");\n }\n }\n const raw = draftToInput(d);\n const parsed = AutomationInput.safeParse(raw);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) set(fieldForPath(issue.path), issue.message);\n }\n const ok = parsed.success && Object.keys(errors).length === 0;\n return { input: ok ? parsed.data : null, errors };\n}\n\n/* ------------------------------------------------------------------ */\n/* History */\n/* ------------------------------------------------------------------ */\n\nexport function occurrenceTime(o: Occurrence): string {\n return o.scheduledFor ?? o.createdAt;\n}\n\n/** Union by id (later lists win), newest first. */\nexport function mergeOccurrences(...lists: (Occurrence[] | undefined | null)[]): Occurrence[] {\n const byId = new Map<string, Occurrence>();\n for (const list of lists) for (const o of list ?? []) byId.set(o.id, o);\n return [...byId.values()].sort(\n (a, b) =>\n b.createdAt.localeCompare(a.createdAt) || occurrenceTime(b).localeCompare(occurrenceTime(a)),\n );\n}\n\n/** Accept `Occurrence[]` or `{items|occurrences: Occurrence[]}`. */\nexport function normalizeHistory(res: unknown): Occurrence[] {\n if (Array.isArray(res)) return res as Occurrence[];\n if (res && typeof res === \"object\") {\n const r = res as { items?: unknown; occurrences?: unknown };\n if (Array.isArray(r.items)) return r.items as Occurrence[];\n if (Array.isArray(r.occurrences)) return r.occurrences as Occurrence[];\n }\n return [];\n}\n\nexport function curlExample(token: string, url: string): string {\n return `curl -X POST -H 'Authorization: Bearer ${token}' -H 'Content-Type: application/json' -d '{}' ${url}`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{_ as e,a as t,f as n,m as r,n as i,t as a}from"./jsx-runtime-D13aM9HY.js";import{bt as o,c as s,d as c,gt as l,n as u,p as d,v as f,vt as p}from"./states-ZhrxQa3K.js";import{t as m}from"./key-round-VDbE9E4X.js";import{Q as h,nt as g,r as _,tt as v}from"./index-hxvDvCS7.js";import{t as y}from"./TextLink-OzzyP2-p.js";import{a as b,c as x,i as S,l as C,n as w,o as T,r as E,s as D,t as O,u as k}from"./logic-B46fwD-8.js";var A={name:`log-in`,size:24,node:[[`path`,{d:`m10 17 5-5-5-5`,key:`1bsop3`}],[`path`,{d:`M15 12H3`,key:`6jk70r`}],[`path`,{d:`M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4`,key:`u53s6r`}]]};A.node;var j=i(A),M=e(r(),1),N=a();function P(){let e=new URLSearchParams(location.hash.replace(/^#/,``)),t=new URLSearchParams(location.search);return e.get(`token`)??t.get(`token`)}function F(){let e=n(),[r]=t(),i=r.get(`next`),a=(0,M.useMemo)(P,[]),l=g(e=>e.status),u=g(e=>e.signedOutReason),d=(0,M.useMemo)(()=>E(),[]),[f,y]=(0,M.useState)(!1),[x,S]=(0,M.useState)(null);return(0,M.useEffect)(()=>{a&&history.replaceState(history.state,``,location.pathname+location.search)},[a]),(0,M.useEffect)(()=>{!a&&l===`authenticated`&&e(v(i),{replace:!0})},[a,l,i,e]),!a&&l===`checking`?(0,N.jsx)(s,{label:`Checking this device…`}):(0,N.jsx)(`div`,{className:`flex min-h-dvh items-start justify-center px-4 safe-pt-10 safe-pb-10 sm:items-center`,children:(0,N.jsxs)(`div`,{className:`w-full max-w-sm rounded-xl border border-border bg-surface p-5 shadow-sm`,children:[(0,N.jsxs)(`div`,{className:`mb-4 flex items-center gap-3`,children:[(0,N.jsx)(`img`,{src:`/icon.svg`,alt:``,className:`size-10 rounded-lg`}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Switchyard`}),(0,N.jsx)(`p`,{className:`text-sm text-muted`,children:a?`Sign in this browser`:`Sign in`})]})]}),u&&(0,N.jsx)(`p`,{role:`status`,className:`mb-3 rounded-md bg-warning-soft px-3 py-2 text-sm`,children:u}),a?(0,N.jsxs)(`form`,{onSubmit:async t=>{if(t.preventDefault(),a){y(!0),S(null);try{await p(`/api/enroll`,{token:a,name:d.slice(0,80),kind:_()?`pwa`:`browser`}),await h()===`authenticated`?e(v(i),{replace:!0}):S({code:`internal`,message:`Signed in, but the coordinator did not accept the new credential. Try again.`})}catch(e){let t=o(e)?e.code:`internal`;S({code:t,message:O[t]??(e instanceof Error?e.message:String(e))})}finally{y(!1)}}},className:`flex flex-col gap-3`,noValidate:!0,children:[(0,N.jsxs)(`p`,{className:`text-sm`,children:[`This single-use link signs in this browser as “`,d,`”. You can rename it in Settings › Devices.`]}),x&&(0,N.jsxs)(`div`,{role:`alert`,className:`rounded-md border border-border bg-danger-soft px-3 py-2 text-sm`,children:[(0,N.jsx)(`div`,{className:`font-medium`,children:b(x.code)}),(0,N.jsx)(`div`,{className:`text-muted`,children:x.message})]}),(0,N.jsx)(c,{type:`submit`,variant:`primary`,"data-testid":`signin-link`,busy:f,disabled:x?.code===`enrollment_expired`||x?.code===`enrollment_used`,icon:(0,N.jsx)(m,{className:`size-4`}),children:`Sign in`})]}):(0,N.jsx)(R,{next:i})]})})}var I=()=>_()?`pwa`:`browser`;function L({title:e,children:t}){return(0,N.jsxs)(`div`,{role:`alert`,className:`rounded-md border border-border bg-danger-soft px-3 py-2 text-sm`,children:[(0,N.jsxs)(`div`,{className:`flex items-center gap-1.5 font-medium`,children:[(0,N.jsx)(f,{"aria-hidden":!0,className:`size-4 shrink-0`}),e]}),(0,N.jsx)(`div`,{className:`break-words text-muted`,children:t})]})}function R({next:e}){let r=n(),i=(0,M.useMemo)(()=>E().slice(0,80),[]),[a,f]=t(),[g,y]=(0,M.useState)(null),[b,x]=(0,M.useState)(null),[w,T]=(0,M.useState)(0),[D,O]=(0,M.useState)(null),[A,P]=(0,M.useState)(()=>{let e=a.get(`error`);return e?{code:e,message:S(e,a.get(`detail`))}:null}),[F,R]=(0,M.useState)(null),B=(0,M.useRef)(null),V=C();(0,M.useEffect)(()=>{if(!a.has(`error`)&&!a.has(`detail`))return;let e=new URLSearchParams(a);e.delete(`error`),e.delete(`detail`),f(e,{replace:!0})},[]),(0,M.useEffect)(()=>{let e=new AbortController;return x(null),l(`/api/setup`,void 0,e.signal).then(t=>!e.signal.aborted&&y(t)).catch(t=>!e.signal.aborted&&x(t)),()=>e.abort()},[w]);let H=e=>{let t=o(e)?e.code:`internal`;e instanceof Error&&e.name===`NotAllowedError`?P({code:t,message:`Passkey sign-in was canceled or timed out.`}):P({code:t,message:o(e)?S(t,e.message):e instanceof Error?e.message:String(e)})},U=(0,M.useCallback)(async()=>{await h()===`authenticated`?r(v(e),{replace:!0}):P({code:`internal`,message:`Signed in, but the coordinator did not accept the new credential. Try again.`})},[r,e]),W=async()=>{O(`passkey`),P(null);try{let{challengeId:e,options:t}=await p(`/api/auth/passkey/options`),n=await V.run(()=>k({optionsJSON:t}));if(!n.ok){P({code:`canceled`,message:`Passkey sign-in was canceled.`});return}let r=n.value;await p(`/api/auth/passkey/verify`,{challengeId:e,response:r,deviceName:i,kind:I()}),await U()}catch(e){H(e)}finally{O(null)}},G=async()=>{O(`oidc`),P(null);let t=_();try{let n=await p(`/api/auth/oidc/begin`,{deviceName:i,kind:I(),next:v(e),handoff:t});if(t&&n.flowId&&n.pollToken)B.current=n.authorizeUrl,R({flowId:n.flowId,pollToken:n.pollToken}),window.open(n.authorizeUrl,`_blank`);else{location.assign(n.authorizeUrl);return}}catch(e){H(e)}O(null)};if(b)return(0,N.jsx)(u,{title:`Cannot reach Switchyard`,error:b,onRetry:()=>T(e=>e+1)});if(!g)return(0,N.jsx)(s,{label:`Checking this server…`});if(F)return(0,N.jsx)(z,{flowId:F.flowId,pollToken:F.pollToken,authorizeUrl:B.current,onDone:U,onExit:()=>R(null)});let K=g.passkey.registered&&g.passkey.available;return(0,N.jsxs)(`div`,{className:`flex flex-col gap-4 text-sm`,children:[(0,N.jsx)(`p`,{className:`text-base font-medium`,children:`Sign in to Switchyard`}),A&&(0,N.jsx)(L,{title:`Sign-in failed`,children:A.message}),(0,N.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[g.oidc&&(0,N.jsx)(c,{"data-testid":`signin-oidc`,variant:`primary`,busy:D===`oidc`,disabled:D!==null,icon:(0,N.jsx)(j,{className:`size-4`}),onClick:G,children:g.oidc.label}),K&&(0,N.jsx)(c,{"data-testid":`signin-passkey`,variant:g.oidc?`secondary`:`primary`,busy:D===`passkey`,disabled:D!==null,icon:(0,N.jsx)(m,{className:`size-4`}),onClick:W,children:`Sign in with a passkey`}),V.waiting&&(0,N.jsxs)(`div`,{role:`status`,className:`flex items-center gap-2 text-sm text-muted`,children:[(0,N.jsx)(d,{}),(0,N.jsx)(`span`,{className:`flex-1`,children:`Waiting for your passkey…`}),(0,N.jsx)(c,{size:`sm`,variant:`ghost`,onClick:V.cancel,children:`Cancel`})]}),g.passkey.registered&&!g.passkey.available&&g.passkey.reason&&(0,N.jsxs)(`p`,{className:`text-xs text-muted`,children:[`Passkeys are unavailable: `,g.passkey.reason,`.`]})]}),!g.oidc&&!K?(0,N.jsxs)(`p`,{"data-testid":`signin-pair-hint`,className:`text-muted`,children:[`No sign-in method is set up. On the machine running Switchyard, run`,` `,(0,N.jsx)(`code`,{children:`switchyard pair`}),` for a single-use sign-in link.`]}):(0,N.jsxs)(`p`,{className:`text-xs text-muted`,children:[`Locked out? Run `,(0,N.jsx)(`code`,{children:`switchyard pair`}),` on the server for a single-use sign-in link.`]})]})}function z({flowId:e,pollToken:t,authorizeUrl:n,onDone:r,onExit:i}){let[a,s]=(0,M.useState)(()=>x(Date.now())),l=(0,M.useRef)(a);l.current=a;let u=(0,M.useRef)(!1),d=(0,M.useRef)(r);d.current=r;let f=(0,M.useCallback)(e=>{let t=T(l.current,e);return l.current=t,s(t),t},[]),m=(0,M.useCallback)(async()=>{if(!(u.current||l.current.phase!==`waiting`)){u.current=!0;try{let n=await p(`/api/auth/oidc/claim`,{flowId:e,pollToken:t});f({type:`claim`,result:n,now:Date.now()}).phase===`done`&&await d.current()}catch(e){f({type:`claim_error`,code:o(e)?e.code:`network`,message:`This sign-in expired or was already used. Start again.`,now:Date.now()})}finally{u.current=!1}}},[e,t,f]);return(0,M.useEffect)(()=>{let e=()=>document.visibilityState===`visible`,t=setInterval(()=>{f({type:`tick`,now:Date.now()}),D(l.current,e())&&m()},w),n=()=>{D(l.current,e())&&m()};return document.addEventListener(`visibilitychange`,n),()=>{clearInterval(t),document.removeEventListener(`visibilitychange`,n)}},[m,f]),a.phase===`timeout`||a.phase===`failed`||a.phase===`canceled`?(0,N.jsxs)(`div`,{"data-testid":`signin-handoff`,className:`flex flex-col gap-3 text-sm`,children:[(0,N.jsx)(L,{title:a.phase===`timeout`?`Sign-in timed out`:`Sign-in stopped`,children:a.phase===`timeout`?`The sign-in was not finished in time. Start again.`:a.message??`Start again.`}),(0,N.jsx)(c,{onClick:i,children:`Back to sign-in`})]}):(0,N.jsxs)(`div`,{"data-testid":`signin-handoff`,role:`status`,className:`flex flex-col gap-3 text-sm`,children:[(0,N.jsx)(`p`,{className:`font-medium`,children:`Finish signing in, then come back here`}),(0,N.jsx)(`p`,{className:`text-muted`,children:`Complete single sign-on in the page that opened, then return to this app. This screen continues on its own.`}),n&&(0,N.jsx)(y,{href:n,external:!0,children:`Open the sign-in page again`}),(0,N.jsx)(c,{onClick:()=>{f({type:`cancel`}),i()},children:`Cancel`})]})}export{F as default,E as defaultDeviceName};
2
+ //# sourceMappingURL=enroll-DwT7AcuS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enroll-DwT7AcuS.js","names":["useMemo","useState","useRef","useCallback","__toESM","useSearchParams","useNavigate","require_react","createLucideIcon","require_jsx_runtime","isApiError","LoadingState","Button","apiGet","ErrorState","Spinner","TriangleAlert","apiPost","KeyRound","checkAuth","useAuth","isStandalone","takeReturnTo","TextLink","enrollErrorTitle","startHandoff","enrollErrorText","usePasskeyCeremony","HANDOFF_POLL_MS","handoffReduce","defaultDeviceName","shouldPoll","ERROR_TEXT","startAuthentication","__iconData","LogIn","import_react","import_jsx_runtime","readToken","hash","query","EnrollView","navigate","params","next","token","status","s","signedOutReason","deviceName","busy","setBusy","error","setError","e","err","code","SignInPanel","kindOf","AlertBox","title","setParams","setup","setSetup","loadError","setLoadError","nonce","setNonce","notice","setNotice","handoff","setHandoff","authorizeUrlRef","ceremony","rest","ac","v","fail","finish","signInWithPasskey","result","options","response","signInWithOidc","standalone","res","n","HandoffScreen","passkeyReady","state","setState","stateRef","inFlight","doneRef","onDone","apply","event","poll","flowId","pollToken","visible","timer","onVisible","onExit","authorizeUrl"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/log-in.mjs","../../src/features/enroll/index.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"log-in\",\n size: 24,\n node: [\n [\"path\", { d: \"m10 17 5-5-5-5\", key: \"1bsop3\" }],\n [\"path\", { d: \"M15 12H3\", key: \"6jk70r\" }],\n [\"path\", { d: \"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\", key: \"u53s6r\" }]\n ]\n};\n__iconData.node;\nconst LogIn = createLucideIcon(__iconData);\n\nexport { __iconData, LogIn as default };\n//# sourceMappingURL=log-in.mjs.map\n","import { startAuthentication } from \"@simplewebauthn/browser\";\nimport type { OidcBeginResponse, OidcClaimResponse, SetupState } from \"@switchyard/protocol\";\nimport { KeyRound, LogIn, TriangleAlert } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useNavigate, useSearchParams } from \"react-router\";\nimport { checkAuth, takeReturnTo, useAuth } from \"../../app/auth\";\nimport { usePasskeyCeremony } from \"../../app/passkeyCeremony\";\nimport { Button } from \"../../components/ui/Button\";\nimport { Spinner } from \"../../components/ui/Spinner\";\nimport { ErrorState, LoadingState } from \"../../components/ui/states\";\nimport { TextLink } from \"../../components/ui/TextLink\";\nimport { isStandalone } from \"../../push\";\nimport { apiGet, apiPost, isApiError } from \"../../sync/api\";\nimport {\n defaultDeviceName,\n ERROR_TEXT,\n enrollErrorText,\n enrollErrorTitle,\n HANDOFF_POLL_MS,\n type HandoffState,\n handoffReduce,\n shouldPoll,\n startHandoff,\n} from \"./logic\";\n\nexport { defaultDeviceName };\n\nfunction readToken(): string | null {\n const hash = new URLSearchParams(location.hash.replace(/^#/, \"\"));\n const query = new URLSearchParams(location.search);\n return hash.get(\"token\") ?? query.get(\"token\");\n}\n\n/**\n * /sign-in: redeem a single-use sign-in link token from `#token=`, or (without\n * one) sign in with single sign-on or a passkey, then\n * return to the deep link that required authentication.\n */\nexport default function EnrollView() {\n const navigate = useNavigate();\n const [params] = useSearchParams();\n const next = params.get(\"next\");\n const token = useMemo(readToken, []);\n const status = useAuth((s) => s.status);\n const signedOutReason = useAuth((s) => s.signedOutReason);\n const deviceName = useMemo(() => defaultDeviceName(), []);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<{ code: string; message: string } | null>(null);\n\n // Keep the token out of the address bar and history.\n useEffect(() => {\n if (token) history.replaceState(history.state, \"\", location.pathname + location.search);\n }, [token]);\n\n // Already enrolled and no token: go back to the deep link.\n useEffect(() => {\n if (!token && status === \"authenticated\") navigate(takeReturnTo(next), { replace: true });\n }, [token, status, next, navigate]);\n\n const submit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!token) return;\n setBusy(true);\n setError(null);\n try {\n await apiPost(\"/api/enroll\", {\n token,\n name: deviceName.slice(0, 80),\n kind: isStandalone() ? \"pwa\" : \"browser\",\n });\n const result = await checkAuth();\n if (result === \"authenticated\") navigate(takeReturnTo(next), { replace: true });\n else\n setError({\n code: \"internal\",\n message: \"Signed in, but the coordinator did not accept the new credential. Try again.\",\n });\n } catch (err) {\n const code = isApiError(err) ? err.code : \"internal\";\n setError({\n code,\n message: ERROR_TEXT[code] ?? (err instanceof Error ? err.message : String(err)),\n });\n } finally {\n setBusy(false);\n }\n };\n\n if (!token && status === \"checking\") return <LoadingState label=\"Checking this device…\" />;\n\n return (\n <div className=\"flex min-h-dvh items-start justify-center px-4 safe-pt-10 safe-pb-10 sm:items-center\">\n <div className=\"w-full max-w-sm rounded-xl border border-border bg-surface p-5 shadow-sm\">\n <div className=\"mb-4 flex items-center gap-3\">\n <img src=\"/icon.svg\" alt=\"\" className=\"size-10 rounded-lg\" />\n <div>\n <h1 className=\"text-lg font-semibold\">Switchyard</h1>\n <p className=\"text-sm text-muted\">{token ? \"Sign in this browser\" : \"Sign in\"}</p>\n </div>\n </div>\n {signedOutReason && (\n <p role=\"status\" className=\"mb-3 rounded-md bg-warning-soft px-3 py-2 text-sm\">\n {signedOutReason}\n </p>\n )}\n {token ? (\n <form onSubmit={submit} className=\"flex flex-col gap-3\" noValidate>\n <p className=\"text-sm\">\n This single-use link signs in this browser as “{deviceName}”. You can rename it in\n Settings › Devices.\n </p>\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-border bg-danger-soft px-3 py-2 text-sm\"\n >\n <div className=\"font-medium\">{enrollErrorTitle(error.code)}</div>\n <div className=\"text-muted\">{error.message}</div>\n </div>\n )}\n <Button\n type=\"submit\"\n variant=\"primary\"\n data-testid=\"signin-link\"\n busy={busy}\n disabled={error?.code === \"enrollment_expired\" || error?.code === \"enrollment_used\"}\n icon={<KeyRound className=\"size-4\" />}\n >\n Sign in\n </Button>\n </form>\n ) : (\n <SignInPanel next={next} />\n )}\n </div>\n </div>\n );\n}\n\ninterface ChallengeResponse {\n challengeId: string;\n options: unknown;\n}\n\nconst kindOf = () => (isStandalone() ? \"pwa\" : \"browser\");\n\nfunction AlertBox({ title, children }: { title: string; children: React.ReactNode }) {\n return (\n <div role=\"alert\" className=\"rounded-md border border-border bg-danger-soft px-3 py-2 text-sm\">\n <div className=\"flex items-center gap-1.5 font-medium\">\n <TriangleAlert aria-hidden className=\"size-4 shrink-0\" />\n {title}\n </div>\n <div className=\"break-words text-muted\">{children}</div>\n </div>\n );\n}\n\n/** The no-token screen: the sign-in options. */\nfunction SignInPanel({ next }: { next: string | null }) {\n const navigate = useNavigate();\n const deviceName = useMemo(() => defaultDeviceName().slice(0, 80), []);\n const [params, setParams] = useSearchParams();\n const [setup, setSetup] = useState<SetupState | null>(null);\n const [loadError, setLoadError] = useState<unknown>(null);\n const [nonce, setNonce] = useState(0);\n const [busy, setBusy] = useState<\"passkey\" | \"oidc\" | null>(null);\n const [notice, setNotice] = useState<{ code: string; message: string } | null>(() => {\n const code = params.get(\"error\");\n return code ? { code, message: enrollErrorText(code, params.get(\"detail\")) } : null;\n });\n const [handoff, setHandoff] = useState<{ flowId: string; pollToken: string } | null>(null);\n const authorizeUrlRef = useRef<string | null>(null);\n const ceremony = usePasskeyCeremony();\n\n // Show a callback error once, then drop it from the address bar.\n // biome-ignore lint/correctness/useExhaustiveDependencies: runs once on mount\n useEffect(() => {\n if (!params.has(\"error\") && !params.has(\"detail\")) return;\n const rest = new URLSearchParams(params);\n rest.delete(\"error\");\n rest.delete(\"detail\");\n setParams(rest, { replace: true });\n }, []);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `nonce` reloads\n useEffect(() => {\n const ac = new AbortController();\n setLoadError(null);\n apiGet<SetupState>(\"/api/setup\", undefined, ac.signal)\n .then((v) => !ac.signal.aborted && setSetup(v))\n .catch((e: unknown) => !ac.signal.aborted && setLoadError(e));\n return () => ac.abort();\n }, [nonce]);\n\n const fail = (err: unknown) => {\n const code = isApiError(err) ? err.code : \"internal\";\n // A canceled or dismissed WebAuthn prompt is not an error worth shouting about.\n if (err instanceof Error && err.name === \"NotAllowedError\") {\n setNotice({ code, message: \"Passkey sign-in was canceled or timed out.\" });\n return;\n }\n setNotice({\n code,\n message: isApiError(err)\n ? enrollErrorText(code, err.message)\n : err instanceof Error\n ? err.message\n : String(err),\n });\n };\n\n const finish = useCallback(async () => {\n const result = await checkAuth();\n if (result === \"authenticated\") navigate(takeReturnTo(next), { replace: true });\n else\n setNotice({\n code: \"internal\",\n message: \"Signed in, but the coordinator did not accept the new credential. Try again.\",\n });\n }, [navigate, next]);\n\n const signInWithPasskey = async () => {\n setBusy(\"passkey\");\n setNotice(null);\n try {\n const { challengeId, options } = await apiPost<ChallengeResponse>(\n \"/api/auth/passkey/options\",\n );\n const result = await ceremony.run(() =>\n startAuthentication({\n optionsJSON: options as Parameters<typeof startAuthentication>[0][\"optionsJSON\"],\n }),\n );\n if (!result.ok) {\n setNotice({ code: \"canceled\", message: \"Passkey sign-in was canceled.\" });\n return;\n }\n const response = result.value;\n await apiPost(\"/api/auth/passkey/verify\", {\n challengeId,\n response,\n deviceName,\n kind: kindOf(),\n });\n await finish();\n } catch (err) {\n fail(err);\n } finally {\n setBusy(null);\n }\n };\n\n const signInWithOidc = async () => {\n setBusy(\"oidc\");\n setNotice(null);\n const standalone = isStandalone();\n try {\n const res = await apiPost<OidcBeginResponse>(\"/api/auth/oidc/begin\", {\n deviceName,\n kind: kindOf(),\n next: takeReturnTo(next),\n handoff: standalone,\n });\n if (standalone && res.flowId && res.pollToken) {\n // Home Screen apps have their own cookie jar: finish in the browser, claim here.\n authorizeUrlRef.current = res.authorizeUrl;\n setHandoff({ flowId: res.flowId, pollToken: res.pollToken });\n window.open(res.authorizeUrl, \"_blank\");\n } else {\n location.assign(res.authorizeUrl);\n return; // leaving the page; keep the button busy\n }\n } catch (err) {\n fail(err);\n }\n setBusy(null);\n };\n\n if (loadError) {\n return (\n <ErrorState\n title=\"Cannot reach Switchyard\"\n error={loadError}\n onRetry={() => setNonce((n) => n + 1)}\n />\n );\n }\n if (!setup) return <LoadingState label=\"Checking this server…\" />;\n\n if (handoff) {\n return (\n <HandoffScreen\n flowId={handoff.flowId}\n pollToken={handoff.pollToken}\n authorizeUrl={authorizeUrlRef.current}\n onDone={finish}\n onExit={() => setHandoff(null)}\n />\n );\n }\n\n const passkeyReady = setup.passkey.registered && setup.passkey.available;\n return (\n <div className=\"flex flex-col gap-4 text-sm\">\n <p className=\"text-base font-medium\">Sign in to Switchyard</p>\n {notice && <AlertBox title=\"Sign-in failed\">{notice.message}</AlertBox>}\n <div className=\"flex flex-col gap-2\">\n {setup.oidc && (\n <Button\n data-testid=\"signin-oidc\"\n variant=\"primary\"\n busy={busy === \"oidc\"}\n disabled={busy !== null}\n icon={<LogIn className=\"size-4\" />}\n onClick={signInWithOidc}\n >\n {setup.oidc.label}\n </Button>\n )}\n {passkeyReady && (\n <Button\n data-testid=\"signin-passkey\"\n variant={setup.oidc ? \"secondary\" : \"primary\"}\n busy={busy === \"passkey\"}\n disabled={busy !== null}\n icon={<KeyRound className=\"size-4\" />}\n onClick={signInWithPasskey}\n >\n Sign in with a passkey\n </Button>\n )}\n {ceremony.waiting && (\n <div role=\"status\" className=\"flex items-center gap-2 text-sm text-muted\">\n <Spinner />\n <span className=\"flex-1\">Waiting for your passkey…</span>\n <Button size=\"sm\" variant=\"ghost\" onClick={ceremony.cancel}>\n Cancel\n </Button>\n </div>\n )}\n {setup.passkey.registered && !setup.passkey.available && setup.passkey.reason && (\n <p className=\"text-xs text-muted\">Passkeys are unavailable: {setup.passkey.reason}.</p>\n )}\n </div>\n {!setup.oidc && !passkeyReady ? (\n <p data-testid=\"signin-pair-hint\" className=\"text-muted\">\n No sign-in method is set up. On the machine running Switchyard, run{\" \"}\n <code>switchyard pair</code> for a single-use sign-in link.\n </p>\n ) : (\n <p className=\"text-xs text-muted\">\n Locked out? Run <code>switchyard pair</code> on the server for a single-use sign-in link.\n </p>\n )}\n </div>\n );\n}\n\n/** PWA single sign-on handoff: finish in the browser, claim the credential here. */\nfunction HandoffScreen({\n flowId,\n pollToken,\n authorizeUrl,\n onDone,\n onExit,\n}: {\n flowId: string;\n pollToken: string;\n authorizeUrl: string | null;\n onDone: () => Promise<void>;\n onExit: () => void;\n}) {\n const [state, setState] = useState<HandoffState>(() => startHandoff(Date.now()));\n const stateRef = useRef(state);\n stateRef.current = state;\n const inFlight = useRef(false);\n const doneRef = useRef(onDone);\n doneRef.current = onDone;\n\n const apply = useCallback((event: Parameters<typeof handoffReduce>[1]) => {\n const next = handoffReduce(stateRef.current, event);\n stateRef.current = next;\n setState(next);\n return next;\n }, []);\n\n const poll = useCallback(async () => {\n if (inFlight.current || stateRef.current.phase !== \"waiting\") return;\n inFlight.current = true;\n try {\n const result = await apiPost<OidcClaimResponse>(\"/api/auth/oidc/claim\", {\n flowId,\n pollToken,\n });\n const next = apply({ type: \"claim\", result, now: Date.now() });\n if (next.phase === \"done\") await doneRef.current();\n } catch (err) {\n apply({\n type: \"claim_error\",\n code: isApiError(err) ? err.code : \"network\",\n message: \"This sign-in expired or was already used. Start again.\",\n now: Date.now(),\n });\n } finally {\n inFlight.current = false;\n }\n }, [flowId, pollToken, apply]);\n\n useEffect(() => {\n const visible = () => document.visibilityState === \"visible\";\n const timer = setInterval(() => {\n apply({ type: \"tick\", now: Date.now() });\n if (shouldPoll(stateRef.current, visible())) void poll();\n }, HANDOFF_POLL_MS);\n const onVisible = () => {\n if (shouldPoll(stateRef.current, visible())) void poll();\n };\n document.addEventListener(\"visibilitychange\", onVisible);\n return () => {\n clearInterval(timer);\n document.removeEventListener(\"visibilitychange\", onVisible);\n };\n }, [poll, apply]);\n\n if (state.phase === \"timeout\" || state.phase === \"failed\" || state.phase === \"canceled\") {\n return (\n <div data-testid=\"signin-handoff\" className=\"flex flex-col gap-3 text-sm\">\n <AlertBox title={state.phase === \"timeout\" ? \"Sign-in timed out\" : \"Sign-in stopped\"}>\n {state.phase === \"timeout\"\n ? \"The sign-in was not finished in time. Start again.\"\n : (state.message ?? \"Start again.\")}\n </AlertBox>\n <Button onClick={onExit}>Back to sign-in</Button>\n </div>\n );\n }\n return (\n <div data-testid=\"signin-handoff\" role=\"status\" className=\"flex flex-col gap-3 text-sm\">\n <p className=\"font-medium\">Finish signing in, then come back here</p>\n <p className=\"text-muted\">\n Complete single sign-on in the page that opened, then return to this app. This screen\n continues on its own.\n </p>\n {authorizeUrl && (\n <TextLink href={authorizeUrl} external>\n Open the sign-in page again\n </TextLink>\n )}\n <Button\n onClick={() => {\n apply({ type: \"cancel\" });\n onExit();\n }}\n >\n Cancel\n </Button>\n </div>\n );\n}\n"],"ignoreList":[0],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1.4s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--default-mono-font-family:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;--color-accent:var(--sy-accent)}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}html,body{background:var(--sy-bg);color:var(--sy-text);font-family:var(--font-sans);overflow-x:clip}body{-webkit-font-smoothing:antialiased;min-height:100dvh;margin:0;line-height:1.5}#root{min-width:0;min-height:100dvh}:focus-visible{outline:2px solid var(--sy-focus);outline-offset:2px}code,pre,kbd,samp{font-family:var(--font-mono)}button,[role=button]{cursor:pointer}button:disabled,[aria-disabled=true]{cursor:not-allowed}}@layer components{@media (pointer:coarse){.tap{min-width:44px;min-height:44px}}.sy-prose{overflow-wrap:anywhere;min-width:0}.sy-prose>*+*{margin-top:.6em}.sy-prose h1,.sy-prose h2,.sy-prose h3,.sy-prose h4{margin-top:1em;font-weight:600;line-height:1.3}.sy-prose h1{font-size:1.25rem}.sy-prose h2{font-size:1.125rem}.sy-prose h3,.sy-prose h4{font-size:1rem}.sy-prose ul{padding-left:1.4em;list-style:outside}.sy-prose ol{padding-left:1.4em;list-style:decimal}.sy-prose a{color:var(--sy-accent);text-underline-offset:2px;text-decoration:underline}.sy-prose blockquote{border-left:3px solid var(--sy-border-strong);color:var(--sy-muted);padding-left:.75em}.sy-prose :not(pre)>code{background:var(--sy-surface-2);border:1px solid var(--sy-border);border-radius:4px;padding:0 .3em;font-size:.875em}.sy-prose hr{border-color:var(--sy-border)}.sy-prose input[type=checkbox]{margin-right:.4em}.sy-prose-compact{font-size:.875rem;line-height:1.5rem}@media (min-width:768px){.sy-prose-compact{font-size:15px}}.sy-prose-compact>*+*{margin-top:.5em}.sy-prose-compact h1{font-size:1.0625rem}.sy-prose-compact h2{font-size:1rem}.sy-prose-compact h2[data-active=true]{background:var(--sy-accent-soft);box-shadow:inset 3px 0 0 var(--sy-accent);border-radius:.375rem;margin-left:-.5rem;padding:.15em .5rem}.sy-prose-compact h3,.sy-prose-compact h4{font-size:.9375rem}.sy-prose-compact h1,.sy-prose-compact h2,.sy-prose-compact h3,.sy-prose-compact h4{margin-top:1.1em;font-weight:600}.sy-prose-compact ul,.sy-prose-compact ol{padding-left:1.2em}.sy-code span[style]{color:var(--shiki-light)}@media (prefers-color-scheme:dark){.sy-code span[style]{color:var(--shiki-dark)}}}@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.\!fixed{position:fixed!important}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-x-2{inset-inline:calc(var(--spacing) * 2)}.inset-y-0{inset-block:0}.-top-0\.5{top:calc(var(--spacing) * -.5)}.-top-1\.5{top:calc(var(--spacing) * -1.5)}.top-0{top:0}.top-1{top:var(--spacing)}.top-1\/2{top:50%}.top-16{top:calc(var(--spacing) * 16)}.top-\[calc\(var\(--safe-top\)\+0\.5rem\)\]{top:calc(var(--safe-top) + .5rem)}.top-full{top:100%}.right-0{right:0}.right-1{right:var(--spacing)}.-bottom-3{bottom:calc(var(--spacing) * -3)}.bottom-0{bottom:0}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing) * 2)}.left-2\.5{left:calc(var(--spacing) * 2.5)}.left-3{left:calc(var(--spacing) * 3)}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.z-\[60\]{z-index:60}.z-\[70\]{z-index:70}.col-start-1{grid-column-start:1}.row-start-2{grid-row-start:2}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.-mx-4{margin-inline:calc(var(--spacing) * -4)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-1{margin-block:var(--spacing)}.-mt-4{margin-top:calc(var(--spacing) * -4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-px{margin-top:1px}.-mr-1\.5{margin-right:calc(var(--spacing) * -1.5)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mr-auto{margin-right:auto}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.-ml-1\.5{margin-left:calc(var(--spacing) * -1.5)}.-ml-2{margin-left:calc(var(--spacing) * -2)}.-ml-px{margin-left:-1px}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-6{-webkit-line-clamp:6;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\!block{display:block!important}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1{height:var(--spacing)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-14{height:calc(var(--spacing) * 14)}.h-\[3px\]{height:3px}.h-auto{height:auto}.h-auto\!{height:auto!important}.h-dvh{height:100dvh}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-\[60vh\]{max-height:60vh}.max-h-\[90dvh\]{max-height:90dvh}.max-h-\[min\(90dvh\,720px\)\]{max-height:min(90dvh,720px)}.max-h-dvh{max-height:100dvh}.min-h-0{min-height:0}.min-h-8{min-height:calc(var(--spacing) * 8)}.min-h-9{min-height:calc(var(--spacing) * 9)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-12{min-height:calc(var(--spacing) * 12)}.min-h-14{min-height:calc(var(--spacing) * 14)}.min-h-dvh{min-height:100dvh}.min-h-full{min-height:100%}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-52{width:calc(var(--spacing) * 52)}.w-56{width:calc(var(--spacing) * 56)}.w-60{width:calc(var(--spacing) * 60)}.w-72{width:calc(var(--spacing) * 72)}.w-96{width:calc(var(--spacing) * 96)}.w-\[6\.25rem\]{width:6.25rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-max{width:max-content}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-32{max-width:calc(var(--spacing) * 32)}.max-w-56{max-width:calc(var(--spacing) * 56)}.max-w-64{max-width:calc(var(--spacing) * 64)}.max-w-\[16rem\]{max-width:16rem}.max-w-\[60vw\]{max-width:60vw}.max-w-\[80ch\]{max-width:80ch}.max-w-\[calc\(100vw-1rem\)\]{max-width:calc(100vw - 1rem)}.max-w-\[min\(20rem\,calc\(100vw-1rem\)\)\]{max-width:min(20rem,100vw - 1rem)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.min-w-48{min-width:calc(var(--spacing) * 48)}.min-w-\[6\.25rem\]{min-width:6.25rem}.min-w-full{min-width:100%}.flex-1{flex:1}.flex-\[1_1_12rem\]{flex:12rem}.flex-\[1_1_15rem\]{flex:15rem}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.basis-48{flex-basis:calc(var(--spacing) * 48)}.basis-full{flex-basis:100%}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-1{--tw-translate-x:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-5{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-1{rotate:1deg}.rotate-90{rotate:90deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-col-resize{cursor:col-resize}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.scroll-mt-14{scroll-margin-top:calc(var(--spacing) * 14)}.scroll-mt-16{scroll-margin-top:calc(var(--spacing) * 16)}.scroll-ml-\[6\.25rem\]{scroll-margin-left:6.25rem}.\[scrollbar-width\:none\]{scrollbar-width:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[auto_minmax\(0\,1fr\)\]{grid-template-columns:auto minmax(0,1fr)}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(320px\,400px\)\]{grid-template-columns:minmax(0,1fr) minmax(320px,400px)}.grid-cols-\[minmax\(0\,2\.4fr\)_minmax\(0\,1fr\)_5\.5rem_minmax\(0\,1\.2fr\)_minmax\(0\,1\.4fr\)_7\.5rem_7rem_auto\]{grid-template-columns:minmax(0,2.4fr) minmax(0,1fr) 5.5rem minmax(0,1.2fr) minmax(0,1.4fr) 7.5rem 7rem auto}.grid-cols-\[minmax\(7rem\,auto\)_1fr\]{grid-template-columns:minmax(7rem,auto) 1fr}.grid-cols-\[repeat\(auto-fit\,minmax\(11rem\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(11rem,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-1\.5{column-gap:calc(var(--spacing) * 1.5)}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-5{column-gap:calc(var(--spacing) * 5)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:var(--spacing)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--sy-border)}.self-center{align-self:center}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.overscroll-contain{overscroll-behavior:contain}.overscroll-x-contain{overscroll-behavior-x:contain}.overscroll-y-contain{overscroll-behavior-y:contain}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:var(--sy-accent)}.border-border{border-color:var(--sy-border)}.border-border-strong{border-color:var(--sy-border-strong)}.border-danger,.border-danger\/50{border-color:var(--sy-danger)}@supports (color:color-mix(in lab, red, red)){.border-danger\/50{border-color:color-mix(in oklab, var(--sy-danger) 50%, transparent)}}.border-info{border-color:var(--sy-info)}.border-transparent{border-color:#0000}.border-warning{border-color:var(--sy-warning)}.bg-accent{background-color:var(--sy-accent)}.bg-accent-fg{background-color:var(--sy-accent-fg)}.bg-accent-soft{background-color:var(--sy-accent-soft)}.bg-bg{background-color:var(--sy-bg)}.bg-border{background-color:var(--sy-border)}.bg-border-strong{background-color:var(--sy-border-strong)}.bg-danger{background-color:var(--sy-danger)}.bg-danger-soft{background-color:var(--sy-danger-soft)}.bg-diff-add{background-color:var(--sy-diff-add)}.bg-diff-del{background-color:var(--sy-diff-del)}.bg-diff-hunk{background-color:var(--sy-diff-hunk)}.bg-info-soft{background-color:var(--sy-info-soft)}.bg-muted{background-color:var(--sy-muted)}.bg-overlay{background-color:var(--sy-overlay)}.bg-subtle{background-color:var(--sy-subtle)}.bg-success{background-color:var(--sy-success)}.bg-success-soft{background-color:var(--sy-success-soft)}.bg-surface{background-color:var(--sy-surface)}.bg-surface-2{background-color:var(--sy-surface-2)}.bg-surface-3{background-color:var(--sy-surface-3)}.bg-transparent{background-color:#0000}.bg-warning{background-color:var(--sy-warning)}.bg-warning-soft{background-color:var(--sy-warning-soft)}.bg-\[conic-gradient\(var\(--sy-surface-2\)_25\%\,var\(--sy-surface\)_0_50\%\,var\(--sy-surface-2\)_0_75\%\,var\(--sy-surface\)_0\)\]{background-image:conic-gradient(var(--sy-surface-2) 25%,var(--sy-surface) 0 50%,var(--sy-surface-2) 0 75%,var(--sy-surface) 0)}.bg-\[length\:16px_16px\]{background-size:16px 16px}.object-cover{object-fit:cover}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.px-0{padding-inline:0}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-7{padding-inline:calc(var(--spacing) * 7)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.pt-1{padding-top:var(--spacing)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.safe-pt{padding-top:var(--safe-top)}.safe-pt-1{padding-top:calc(var(--spacing) * 1 + var(--safe-top))}.safe-pt-1\.5{padding-top:calc(var(--spacing) * 1.5 + var(--safe-top))}.safe-pt-4{padding-top:calc(var(--spacing) * 4 + var(--safe-top))}.safe-pt-10{padding-top:calc(var(--spacing) * 10 + var(--safe-top))}.safe-px{padding-left:var(--safe-left);padding-right:var(--safe-right)}.pr-1{padding-right:var(--spacing)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-7{padding-right:calc(var(--spacing) * 7)}.pb-1{padding-bottom:var(--spacing)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-8{padding-bottom:calc(var(--spacing) * 8)}.safe-pb{padding-bottom:var(--safe-bottom)}.safe-pb-2{padding-bottom:calc(var(--spacing) * 2 + var(--safe-bottom))}.safe-pb-10{padding-bottom:calc(var(--spacing) * 10 + var(--safe-bottom))}.pl-1{padding-left:var(--spacing)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5{padding-left:calc(var(--spacing) * 5)}.pl-6{padding-left:calc(var(--spacing) * 6)}.pl-7{padding-left:calc(var(--spacing) * 7)}.pl-8{padding-left:calc(var(--spacing) * 8)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-normal{white-space:normal}.whitespace-normal\!{white-space:normal!important}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--sy-accent)}.text-accent-fg{color:var(--sy-accent-fg)}.text-danger{color:var(--sy-danger)}.text-danger-fg{color:var(--sy-danger-fg)}.text-info{color:var(--sy-info)}.text-inherit{color:inherit}.text-muted{color:var(--sy-muted)}.text-subtle{color:var(--sy-subtle)}.text-success{color:var(--sy-success)}.text-text{color:var(--sy-text)}.text-warning{color:var(--sy-warning)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.accent-\[var\(--color-accent\)\]{accent-color:var(--color-accent)}.accent-\[var\(--sy-accent\)\]{accent-color:var(--sy-accent)}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-100{opacity:1}.shadow-pop{--tw-shadow:var(--sy-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-4{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-accent{--tw-ring-color:var(--sy-accent)}.ring-accent-soft{--tw-ring-color:var(--sy-accent-soft)}.ring-offset-2{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.ring-offset-bg{--tw-ring-offset-color:var(--sy-bg)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.-outline-offset-1{outline-offset:calc(1px * -1)}.outline-warning{outline-color:var(--sy-warning)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.\[overflow-anchor\:none\]{overflow-anchor:none}.group-open\:rotate-90:is(:where(.group):is([open],:popover-open,:open) *){rotate:90deg}@media (hover:hover){.group-hover\:w-0\.5:is(:where(.group):hover *){width:calc(var(--spacing) * .5)}.group-hover\:bg-accent:is(:where(.group):hover *){background-color:var(--sy-accent)}.group-hover\:opacity-100:is(:where(.group):hover *),.group-hover\/row\:opacity-100:is(:where(.group\/row):hover *){opacity:1}}.group-focus-visible\:w-0\.5:is(:where(.group):focus-visible *){width:calc(var(--spacing) * .5)}.group-focus-visible\:bg-accent:is(:where(.group):focus-visible *){background-color:var(--sy-accent)}.group-has-\[input\:focus-visible\]\:outline-2:is(:where(.group):has(:is(input:focus-visible)) *){outline-style:var(--tw-outline-style);outline-width:2px}.group-has-\[input\:focus-visible\]\:outline-offset-2:is(:where(.group):has(:is(input:focus-visible)) *){outline-offset:2px}.group-has-\[input\:focus-visible\]\:outline-accent:is(:where(.group):has(:is(input:focus-visible)) *){outline-color:var(--sy-accent)}.placeholder\:text-subtle::placeholder{color:var(--sy-subtle)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:inset-x-0:before{content:var(--tw-content);inset-inline:0}.before\:-top-3:before{content:var(--tw-content);top:calc(var(--spacing) * -3)}.before\:bottom-0:before{content:var(--tw-content);bottom:0}.before\:content-\[\'\'\]:before{--tw-content:"";content:var(--tw-content)}.first\:pt-0:first-child{padding-top:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.last\:pb-0:last-child{padding-bottom:0}@media (hover:hover){.hover\:border-accent-hover:hover{border-color:var(--sy-accent-hover)}.hover\:border-danger-hover:hover{border-color:var(--sy-danger-hover)}.hover\:bg-accent-hover:hover{background-color:var(--sy-accent-hover)}.hover\:bg-accent-soft:hover{background-color:var(--sy-accent-soft)}.hover\:bg-border:hover{background-color:var(--sy-border)}.hover\:bg-danger-hover:hover{background-color:var(--sy-danger-hover)}.hover\:bg-danger-soft:hover{background-color:var(--sy-danger-soft)}.hover\:bg-surface-2:hover{background-color:var(--sy-surface-2)}.hover\:text-text:hover{color:var(--sy-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:not-sr-only:focus{clip-path:none;white-space:normal;width:auto;height:auto;margin:0;padding:0;position:static;overflow:visible}.focus\:fixed:focus{position:fixed}.focus\:top-2:focus{top:calc(var(--spacing) * 2)}.focus\:left-2:focus{left:calc(var(--spacing) * 2)}.focus\:border-accent:focus{border-color:var(--sy-accent)}.focus\:bg-surface-2:focus{background-color:var(--sy-surface-2)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:underline:focus-visible{text-decoration-line:underline}.focus-visible\:opacity-100:focus-visible{opacity:1}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-0:focus-visible{outline-offset:0px}.focus-visible\:outline-offset-\[-2px\]:focus-visible{outline-offset:-2px}.focus-visible\:outline-\[var\(--sy-focus\)\]:focus-visible{outline-color:var(--sy-focus)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\:outline-solid:focus-visible{--tw-outline-style:solid;outline-style:solid}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-55:disabled{opacity:.55}.disabled\:opacity-60:disabled{opacity:.6}.has-\[\:focus-visible\]\:outline-2:has(:focus-visible){outline-style:var(--tw-outline-style);outline-width:2px}.has-\[\:focus-visible\]\:outline-offset-1:has(:focus-visible){outline-offset:1px}.has-\[\:focus-visible\]\:outline-offset-2:has(:focus-visible){outline-offset:2px}.has-\[\:focus-visible\]\:outline-accent:has(:focus-visible){outline-color:var(--sy-accent)}.has-\[\[data-testid\=document-interaction\]\]\:max-w-none:has([data-testid=document-interaction]){max-width:none}.aria-\[current\=true\]\:border-accent[aria-current=true]{border-color:var(--sy-accent)}.aria-\[current\=true\]\:text-text[aria-current=true]{color:var(--sy-text)}.aria-\[invalid\=true\]\:border-danger[aria-invalid=true],.aria-\[invalid\=true\]\:focus\:border-danger[aria-invalid=true]:focus{border-color:var(--sy-danger)}@media not all and (min-width:379px){.max-\[379px\]\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.max-\[379px\]\:hidden{display:none}}@media not all and (min-width:48rem){.max-md\:static{position:static}.max-md\:hidden{display:none}.max-md\:overflow-hidden{overflow:hidden}.max-md\:opacity-100{opacity:1}}@media not all and (min-width:40rem){.max-sm\:w-full{width:100%}.max-sm\:basis-full{flex-basis:100%}}@media (min-width:380px){.min-\[380px\]\:hidden{display:none}}@media (min-width:1800px){.min-\[1800px\]\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}}@media (min-width:40rem){.sm\:col-span-2{grid-column:span 2/span 2}.sm\:col-start-auto{grid-column-start:auto}.sm\:row-start-auto{grid-row-start:auto}.sm\:mb-0{margin-bottom:0}.sm\:ml-auto{margin-left:auto}.sm\:hidden{display:none}.sm\:inline{display:inline}.sm\:max-w-48{max-width:calc(var(--spacing) * 48)}.sm\:flex-1{flex:1}.sm\:basis-auto{flex-basis:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto}.sm\:grid-cols-\[minmax\(8rem\,12rem\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(8rem,12rem) minmax(0,1fr)}.sm\:flex-row{flex-direction:row}.sm\:flex-wrap{flex-wrap:wrap}.sm\:items-center{align-items:center}.sm\:items-start{align-items:flex-start}.sm\:justify-center{justify-content:center}.sm\:text-center{text-align:center}}@media (min-width:48rem){.md\:sticky{position:sticky}.md\:-top-3{top:calc(var(--spacing) * -3)}.md\:top-0{top:0}.md\:top-auto{top:auto}.md\:bottom-\[calc\(var\(--safe-bottom\)\+1rem\)\]{bottom:calc(var(--safe-bottom) + 1rem)}.md\:-mx-6{margin-inline:calc(var(--spacing) * -6)}.md\:mx-6{margin-inline:calc(var(--spacing) * 6)}.md\:block{display:block}.md\:grid{display:grid}.md\:h-8{height:calc(var(--spacing) * 8)}.md\:grid-cols-\[13rem_minmax\(0\,1fr\)\]{grid-template-columns:13rem minmax(0,1fr)}.md\:flex-row{flex-direction:row}.md\:flex-wrap{flex-wrap:wrap}.md\:items-end{align-items:flex-end}.md\:gap-3{gap:calc(var(--spacing) * 3)}.md\:gap-8{gap:calc(var(--spacing) * 8)}.md\:px-4{padding-inline:calc(var(--spacing) * 4)}.md\:px-6{padding-inline:calc(var(--spacing) * 6)}.md\:text-center{text-align:center}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media (min-width:64rem){.lg\:inline{display:inline}}@media (min-width:80rem){.xl\:hidden{display:none}.xl\:inline{display:inline}.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:items-start{align-items:flex-start}}@media (min-width:96rem){.\32 xl\:max-w-\[100ch\]{max-width:100ch}.\32 xl\:grid-cols-\[15rem_minmax\(0\,1fr\)\]{grid-template-columns:15rem minmax(0,1fr)}}.\[\&_h2\]\:scroll-mt-14 h2{scroll-margin-top:calc(var(--spacing) * 14)}.\[\&_td\]\:min-w-28 td{min-width:calc(var(--spacing) * 28)}.\[\&_td\]\:border td{border-style:var(--tw-border-style);border-width:1px}.\[\&_td\]\:border-border td{border-color:var(--sy-border)}.\[\&_td\]\:px-2 td{padding-inline:calc(var(--spacing) * 2)}.\[\&_td\]\:py-1 td{padding-block:var(--spacing)}.\[\&_td\]\:align-top td{vertical-align:top}.\[\&_th\]\:min-w-28 th{min-width:calc(var(--spacing) * 28)}.\[\&_th\]\:border th{border-style:var(--tw-border-style);border-width:1px}.\[\&_th\]\:border-border th{border-color:var(--sy-border)}.\[\&_th\]\:bg-surface-2 th{background-color:var(--sy-surface-2)}.\[\&_th\]\:px-2 th{padding-inline:calc(var(--spacing) * 2)}.\[\&_th\]\:py-1 th{padding-block:var(--spacing)}.\[\&_th\]\:text-left th{text-align:left}.\[\&\:\:-moz-range-thumb\]\:size-4::-moz-range-thumb{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}.\[\&\:\:-webkit-slider-thumb\]\:size-4::-webkit-slider-thumb{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb{appearance:none}.\[\&\>span\]\:sr-only>span{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (pointer:coarse){.\[\@media\(pointer\:coarse\)\]\:opacity-100{opacity:1}.\[\@media\(pointer\:coarse\)\]\:before\:-top-6:before{content:var(--tw-content);top:calc(var(--spacing) * -6)}}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--sy-bg:#f8fafc;--sy-surface:#fff;--sy-surface-2:#f1f5f9;--sy-surface-3:#e2e8f0;--sy-border:#d5dce5;--sy-border-strong:#94a3b8;--sy-text:#0f172a;--sy-muted:#475569;--sy-subtle:#64748b;--sy-accent:#2563eb;--sy-accent-hover:#1d4ed8;--sy-accent-fg:#fff;--sy-accent-soft:#dbeafe;--sy-success:#15803d;--sy-success-soft:#dcfce7;--sy-warning:#b45309;--sy-warning-soft:#fef3c7;--sy-danger:#b91c1c;--sy-danger-hover:#991b1b;--sy-danger-fg:#fff;--sy-danger-soft:#fee2e2;--sy-info:#0369a1;--sy-info-soft:#e0f2fe;--sy-diff-add:#e6f6ea;--sy-diff-del:#fbe9e9;--sy-diff-hunk:#eef2f7;--sy-focus:#2563eb;--sy-overlay:#0f172a66;--sy-shadow:0 10px 30px #0f172a1f, 0 2px 6px #0f172a14;--rail-width:64px;--rail-expanded-width:200px;--bottom-nav-height:56px;--safe-top:env(safe-area-inset-top,0px);--safe-right:env(safe-area-inset-right,0px);--safe-bottom:env(safe-area-inset-bottom,0px);--safe-left:env(safe-area-inset-left,0px)}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;--sy-bg:#0f1115;--sy-surface:#161a20;--sy-surface-2:#1d222a;--sy-surface-3:#262c36;--sy-border:#2e3541;--sy-border-strong:#4b5565;--sy-text:#e6e9ee;--sy-muted:#a3acb9;--sy-subtle:#8892a0;--sy-accent:#60a5fa;--sy-accent-hover:#93c5fd;--sy-accent-fg:#0b1220;--sy-accent-soft:#1e3a5f;--sy-success:#4ade80;--sy-success-soft:#14321f;--sy-warning:#fbbf24;--sy-warning-soft:#3a2c0c;--sy-danger:#f87171;--sy-danger-hover:#fca5a5;--sy-danger-fg:#1f0a0a;--sy-danger-soft:#3b1515;--sy-info:#38bdf8;--sy-info-soft:#0c2a3a;--sy-diff-add:#12291b;--sy-diff-del:#2f1517;--sy-diff-hunk:#1b2330;--sy-focus:#93c5fd;--sy-overlay:#0000008c;--sy-shadow:0 10px 30px #00000080, 0 2px 6px #0006}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}.animate-spin{animation:2.4s linear infinite spin!important}.sy-motion{transition-duration:.2s!important}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}