@turmind/halo 0.1.9 → 0.2.1-bc7cf2b

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 (66) hide show
  1. package/README.md +1 -5
  2. package/admin-out/404.html +1 -1
  3. package/admin-out/_next/static/chunks/212-170855bed19f67f3.js +1 -0
  4. package/admin-out/_next/static/chunks/{503-7c6d9935df6e0cea.js → 307-d7a99f9a4a436ec3.js} +1 -1
  5. package/admin-out/_next/static/chunks/525.2c10a4fd329d0d24.js +1 -0
  6. package/admin-out/_next/static/chunks/app/layout-c2fa8035998e48d5.js +1 -0
  7. package/admin-out/_next/static/chunks/app/page-31317ef1fb0ba31f.js +1 -0
  8. package/admin-out/_next/static/chunks/{webpack-8bd7ef88a6527feb.js → webpack-47520cdc55be63e7.js} +1 -1
  9. package/admin-out/_next/static/css/66df341f99220f5c.css +3 -0
  10. package/admin-out/index.html +1 -1
  11. package/admin-out/index.txt +21 -20
  12. package/bundled-docs/design/agent.md +1 -1
  13. package/bundled-docs/design/evolution.md +11 -2
  14. package/bundled-docs/design/halo-city.md +31 -0
  15. package/bundled-docs/design/prompt-system.md +3 -3
  16. package/bundled-docs/design/session.md +26 -1
  17. package/bundled-docs/design/storage.md +13 -0
  18. package/bundled-docs/dev/acp-adapter.md +31 -4
  19. package/bundled-docs/dev/api.md +6 -4
  20. package/bundled-docs/dev/desktop-packaging.md +98 -8
  21. package/bundled-docs/dev/env.md +4 -2
  22. package/bundled-docs/dev/previews.md +3 -0
  23. package/bundled-docs/dev/tools.md +3 -1
  24. package/bundled-docs/guide/cli.md +40 -16
  25. package/bundled-docs/guide/getting-started.md +3 -2
  26. package/bundled-docs/requirements/editor.md +1 -1
  27. package/bundled-docs/requirements/explorer.md +11 -0
  28. package/dist/index.js +14102 -13249
  29. package/package.json +1 -2
  30. package/templates/INSTRUCTIONS.md +0 -4
  31. package/templates/agents/__apply_agent__/AGENT.md +41 -19
  32. package/templates/agents/__evo_agent__/AGENT.md +73 -45
  33. package/templates/agents/__evo_agent__/agent.yaml +9 -6
  34. package/templates/agents/__score__/AGENT.md +65 -33
  35. package/templates/agents/deep-executor/AGENT.md +23 -6
  36. package/templates/agents/deep-executor/agent.yaml +4 -1
  37. package/templates/agents/default/AGENT.md +32 -8
  38. package/templates/agents/executor/AGENT.md +19 -1
  39. package/templates/agents/executor/agent.yaml +6 -3
  40. package/templates/models/aws-bedrock-claude-invoke.yaml +53 -0
  41. package/templates/prompts/all/WORKSPACE_CONVENTIONS.md +5 -0
  42. package/templates/prompts/bootstrap/BOOTSTRAP.md +4 -0
  43. package/templates/prompts/root/WORKSPACE_MEMORY.md +2 -0
  44. package/templates/skills/acp/SKILL.md +8 -1
  45. package/templates/skills/acp/templates/SKILL.md.tmpl +2 -1
  46. package/templates/skills/acp/templates/ask.py +2 -1
  47. package/templates/skills/acp/templates/config.yaml.tmpl +5 -0
  48. package/admin-out/_next/static/chunks/298-d6b224b569da4de0.js +0 -1
  49. package/admin-out/_next/static/chunks/661.a4fe93f3f2a5e871.js +0 -1
  50. package/admin-out/_next/static/chunks/app/layout-58f773336e6fce61.js +0 -1
  51. package/admin-out/_next/static/chunks/app/page-cc8043335282d745.js +0 -1
  52. package/admin-out/_next/static/css/8fce4e1a54dac12a.css +0 -3
  53. package/bundled-docs/plans/cron-tasks.md +0 -362
  54. package/bundled-docs/plans/design-suggestions.md +0 -203
  55. package/bundled-docs/plans/issue-session-deep-nesting.md +0 -208
  56. package/bundled-docs/plans/launch-plan.md +0 -111
  57. package/bundled-docs/plans/md-and-agent-refactor.md +0 -197
  58. package/bundled-docs/plans/remote-mac-worker.md +0 -196
  59. package/bundled-docs/plans/roadmap.md +0 -40
  60. package/bundled-docs/plans/self-evolution.md +0 -1379
  61. package/bundled-docs/plans/todo.md +0 -32
  62. package/bundled-docs/plans/weixin-channel.md +0 -255
  63. package/bundled-docs/test/docs-seeding.md +0 -101
  64. package/bundled-docs/test/session.md +0 -374
  65. /package/admin-out/_next/static/{IBP_mwBDf-cPwZSZZGpi8 → iSrc6429pyTB0lK-EE5oH}/_buildManifest.js +0 -0
  66. /package/admin-out/_next/static/{IBP_mwBDf-cPwZSZZGpi8 → iSrc6429pyTB0lK-EE5oH}/_ssgManifest.js +0 -0
@@ -1,3 +0,0 @@
1
- @font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/ba9851c3c22cd980-s.woff2) format("woff2");unicode-range:u+0460-052f,u+1c80-1c8a,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/21350d82a1f187e9-s.woff2) format("woff2");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/c5fe6dc8356a8c31-s.woff2) format("woff2");unicode-range:u+1f??}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/19cfc7226ec3afaa-s.woff2) format("woff2");unicode-range:u+0370-0377,u+037a-037f,u+0384-038a,u+038c,u+038e-03a1,u+03a3-03ff}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/df0a9ae256c0569c-s.woff2) format("woff2");unicode-range:u+0102-0103,u+0110-0111,u+0128-0129,u+0168-0169,u+01a0-01a1,u+01af-01b0,u+0300-0301,u+0303-0304,u+0308-0309,u+0323,u+0329,u+1ea0-1ef9,u+20ab}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/8e9860b6e62d6359-s.woff2) format("woff2");unicode-range:u+0100-02ba,u+02bd-02c5,u+02c7-02cc,u+02ce-02d7,u+02dd-02ff,u+0304,u+0308,u+0329,u+1d00-1dbf,u+1e00-1e9f,u+1ef2-1eff,u+2020,u+20a0-20ab,u+20ad-20c0,u+2113,u+2c60-2c7f,u+a720-a7ff}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/_next/static/media/e4af272ccee01ff0-s.p.woff2) format("woff2");unicode-range:u+00??,u+0131,u+0152-0153,u+02bb-02bc,u+02c6,u+02da,u+02dc,u+0304,u+0308,u+0329,u+2000-206f,u+20ac,u+2122,u+2191,u+2193,u+2212,u+2215,u+feff,u+fffd}@font-face{font-family:Inter Fallback;src:local("Arial");ascent-override:90.44%;descent-override:22.52%;line-gap-override:0.00%;size-adjust:107.12%}.__className_f367f3{font-family:Inter,Inter Fallback;font-style:normal}.__variable_f367f3{--font-inter:"Inter","Inter Fallback"}
2
-
3
- /*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,::backdrop,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:""}}}@layer theme{:host,:root{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-900:oklch(37.8% .077 168.94);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-300:oklch(85.5% .138 181.071);--color-teal-500:oklch(70.4% .14 182.503);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-sky-50:oklch(97.7% .013 236.62);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-700:oklch(50% .134 242.749);--color-sky-950:oklch(29.3% .066 243.157);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-300:oklch(78.5% .115 274.713);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-900:oklch(38.1% .176 304.987);--color-purple-950:oklch(29.1% .149 302.717);--color-pink-300:oklch(82.3% .12 346.018);--color-pink-400:oklch(71.8% .202 349.761);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1) infinite;--blur-sm:8px;--aspect-video:16/9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,::backdrop,:after,:before{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}:host,html{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{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{outline:auto}progress{vertical-align:baseline}summary{display:list-item}menu,ol,ul{list-style:none}audio,canvas,embed,iframe,img,object,svg,video{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,optgroup,select,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,::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-second-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,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.-top-0\.5{top:calc(var(--spacing) * -.5)}.-top-1{top:calc(var(--spacing) * -1)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-\[calc\(100\%\+2px\)\]{top:calc(100% + 2px)}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing) * -.5)}.-right-1{right:calc(var(--spacing) * -1)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-1{bottom:calc(var(--spacing) * -1)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-1{bottom:calc(var(--spacing) * 1)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-full{bottom:100%}.-left-1{left:calc(var(--spacing) * -1)}.left-0{left:calc(var(--spacing) * 0)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing) * 2)}.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}.col-span-2{grid-column:span 2/span 2}.float-right{float:right}.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}}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1{margin-block:calc(var(--spacing) * 1)}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-sm{font-size:.875rem;line-height:1.71429}.prose-sm :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em;padding-inline-start:1.11111em}.prose-sm :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:.8em;font-size:2.14286em;line-height:1.2}.prose-sm :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.6em;margin-bottom:.8em;font-size:1.42857em;line-height:1.4}.prose-sm :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.55556em;margin-bottom:.444444em;font-size:1.28571em;line-height:1.55556}.prose-sm :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.42857em;margin-bottom:.571429em;line-height:1.42857}.prose-sm :where(img):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.142857em;padding-inline-end:.357143em;padding-bottom:.142857em;border-radius:.3125rem;padding-inline-start:.357143em;font-size:.857143em}.prose-sm :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em}.prose-sm :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.9em}.prose-sm :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em}.prose-sm :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;border-radius:.25rem;margin-top:1.66667em;margin-bottom:1.66667em;padding-inline-start:1em;font-size:.857143em;line-height:1.66667}.prose-sm :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em;padding-inline-start:1.57143em}.prose-sm :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;margin-bottom:.285714em}.prose-sm :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.428571em}.prose-sm :where(.prose-sm>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(.prose-sm>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(.prose-sm>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.14286em}.prose-sm :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.571429em;margin-bottom:.571429em}.prose-sm :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em;margin-bottom:1.14286em}.prose-sm :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.14286em}.prose-sm :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.285714em;padding-inline-start:1.57143em}.prose-sm :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2.85714em;margin-bottom:2.85714em}.prose-sm :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-sm :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.857143em;line-height:1.5}.prose-sm :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.666667em;padding-inline-end:1em;padding-bottom:.666667em;padding-inline-start:1em}.prose-sm :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-sm :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-sm :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.71429em;margin-bottom:1.71429em}.prose-sm :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-sm :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;font-size:.857143em;line-height:1.33333}.prose-sm :where(.prose-sm>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-sm :where(.prose-sm>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.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-0\.5{margin-left:calc(var(--spacing) * -.5)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-6{margin-left:calc(var(--spacing) * 6)}.ml-\[22px\]{margin-left:22px}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-2,.line-clamp-3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-video{aspect-ratio:var(--aspect-video)}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-4\.5{height:calc(var(--spacing) * 4.5)}.h-5{height:calc(var(--spacing) * 5)}.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-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-64{height:calc(var(--spacing) * 64)}.h-\[35px\]{height:35px}.h-\[80vh\]{height:80vh}.h-\[92vh\]{height:92vh}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-60{max-height:calc(var(--spacing) * 60)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-\[40vh\]{max-height:40vh}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.max-h-\[70vh\]{max-height:70vh}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[200px\]{max-height:200px}.max-h-\[400px\]{max-height:400px}.max-h-\[420px\]{max-height:420px}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-full{min-height:100%}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\.5{width:calc(var(--spacing) * 4.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-\[96vw\]{width:96vw}.w-\[160px\]{width:160px}.w-\[220px\]{width:220px}.w-\[400px\]{width:400px}.w-\[420px\]{width:420px}.w-\[460px\]{width:460px}.w-\[480px\]{width:480px}.w-\[560px\]{width:560px}.w-\[640px\]{width:640px}.w-\[800px\]{width:800px}.w-\[min\(80vw\,480px\)\]{width:min(80vw,480px)}.w-\[min\(520px\,80\%\)\]{width:min(520px,80%)}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.max-w-20{max-width:calc(var(--spacing) * 20)}.max-w-24{max-width:calc(var(--spacing) * 24)}.max-w-32{max-width:calc(var(--spacing) * 32)}.max-w-36{max-width:calc(var(--spacing) * 36)}.max-w-40{max-width:calc(var(--spacing) * 40)}.max-w-\[80px\]{max-width:80px}.max-w-\[90vw\]{max-width:90vw}.max-w-\[92vw\]{max-width:92vw}.max-w-\[94vw\]{max-width:94vw}.max-w-\[240px\]{max-width:240px}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-prose{max-width:65ch}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[3ch\]{min-width:3ch}.min-w-\[14px\]{min-width:14px}.min-w-\[140px\]{min-width:140px}.min-w-\[160px\]{min-width:160px}.min-w-\[280px\]{min-width:280px}.min-w-full{min-width:100%}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1)}.-translate-x-1\/2,.-translate-y-1\/2{translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1)}.-rotate-90{rotate:-90deg}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-ew-resize{cursor:ew-resize}.cursor-move{cursor:move}.cursor-nesw-resize{cursor:nesw-resize}.cursor-not-allowed{cursor:not-allowed}.cursor-ns-resize{cursor:ns-resize}.cursor-nwse-resize{cursor:nwse-resize}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\[1fr_1fr_80px\]{grid-template-columns:1fr 1fr 80px}.grid-cols-\[repeat\(auto-fill\,minmax\(220px\,1fr\)\)\]{grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:calc(var(--spacing) * 0)}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.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-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}: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-\[var\(--border\)\]>:not(:last-child)){border-color:var(--border)}.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}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e+38px}.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{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-b-lg{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.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-\[var\(--border\)\],.border-\[var\(--border\)\]\/10{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-\[var\(--border\)\]\/10{border-color:color-mix(in oklab,var(--border) 10%,transparent)}}.border-\[var\(--border\)\]\/30{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-\[var\(--border\)\]\/30{border-color:color-mix(in oklab,var(--border) 30%,transparent)}}.border-\[var\(--border\)\]\/50{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-\[var\(--border\)\]\/50{border-color:color-mix(in oklab,var(--border) 50%,transparent)}}.border-\[var\(--destructive\)\]{border-color:var(--destructive)}.border-\[var\(--primary\)\],.border-\[var\(--primary\)\]\/30{border-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.border-\[var\(--primary\)\]\/30{border-color:color-mix(in oklab,var(--primary) 30%,transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/30{border-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.border-amber-700{border-color:var(--color-amber-700)}.border-blue-500\/20{border-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/20{border-color:color-mix(in oklab,var(--color-blue-500) 20%,transparent)}}.border-blue-700{border-color:var(--color-blue-700)}.border-emerald-700{border-color:var(--color-emerald-700)}.border-green-500\/20{border-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.border-green-500\/20{border-color:color-mix(in oklab,var(--color-green-500) 20%,transparent)}}.border-purple-900\/50{border-color:#59168b80}@supports (color:color-mix(in lab,red,red)){.border-purple-900\/50{border-color:color-mix(in oklab,var(--color-purple-900) 50%,transparent)}}.border-purple-900\/60{border-color:#59168b99}@supports (color:color-mix(in lab,red,red)){.border-purple-900\/60{border-color:color-mix(in oklab,var(--color-purple-900) 60%,transparent)}}.border-red-500\/50{border-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.border-red-500\/50{border-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.border-red-700{border-color:var(--color-red-700)}.border-slate-900{border-color:var(--color-slate-900)}.border-transparent{border-color:#0000}.border-zinc-600{border-color:var(--color-zinc-600)}.border-zinc-700\/40{border-color:#3f3f4666}@supports (color:color-mix(in lab,red,red)){.border-zinc-700\/40{border-color:color-mix(in oklab,var(--color-zinc-700) 40%,transparent)}}.border-zinc-800{border-color:var(--color-zinc-800)}.border-l-blue-500{border-left-color:var(--color-blue-500)}.border-l-emerald-500\/70{border-left-color:#00bb7fb3}@supports (color:color-mix(in lab,red,red)){.border-l-emerald-500\/70{border-left-color:color-mix(in oklab,var(--color-emerald-500) 70%,transparent)}}.border-l-purple-500\/70{border-left-color:#ac4bffb3}@supports (color:color-mix(in lab,red,red)){.border-l-purple-500\/70{border-left-color:color-mix(in oklab,var(--color-purple-500) 70%,transparent)}}.bg-\[\#0a0a0a\]{background-color:#0a0a0a}.bg-\[\#1a1a1a\]{background-color:#1a1a1a}.bg-\[\#111\]{background-color:#111}.bg-\[var\(--accent\)\],.bg-\[var\(--accent\)\]\/30{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--accent\)\]\/30{background-color:color-mix(in oklab,var(--accent) 30%,transparent)}}.bg-\[var\(--accent\)\]\/80{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--accent\)\]\/80{background-color:color-mix(in oklab,var(--accent) 80%,transparent)}}.bg-\[var\(--background\)\],.bg-\[var\(--background\)\]\/50{background-color:var(--background)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--background\)\]\/50{background-color:color-mix(in oklab,var(--background) 50%,transparent)}}.bg-\[var\(--background\)\]\/80{background-color:var(--background)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--background\)\]\/80{background-color:color-mix(in oklab,var(--background) 80%,transparent)}}.bg-\[var\(--border\)\]{background-color:var(--border)}.bg-\[var\(--card\)\]{background-color:var(--card)}.bg-\[var\(--destructive\)\],.bg-\[var\(--destructive\)\]\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--destructive\)\]\/10{background-color:color-mix(in oklab,var(--destructive) 10%,transparent)}}.bg-\[var\(--foreground\)\]{background-color:var(--foreground)}.bg-\[var\(--muted\)\]\/50{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--muted\)\]\/50{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.bg-\[var\(--muted-foreground\)\]{background-color:var(--muted-foreground)}.bg-\[var\(--primary\)\],.bg-\[var\(--primary\)\]\/10{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--primary\)\]\/10{background-color:color-mix(in oklab,var(--primary) 10%,transparent)}}.bg-\[var\(--primary\)\]\/20{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--primary\)\]\/20{background-color:color-mix(in oklab,var(--primary) 20%,transparent)}}.bg-\[var\(--secondary\)\],.bg-\[var\(--secondary\)\]\/30{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--secondary\)\]\/30{background-color:color-mix(in oklab,var(--secondary) 30%,transparent)}}.bg-\[var\(--secondary\)\]\/50{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.bg-\[var\(--secondary\)\]\/50{background-color:color-mix(in oklab,var(--secondary) 50%,transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/10{background-color:#fcbb001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-400\/10{background-color:color-mix(in oklab,var(--color-amber-400) 10%,transparent)}}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-500\/15{background-color:#f99c0026}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/15{background-color:color-mix(in oklab,var(--color-amber-500) 15%,transparent)}}.bg-amber-600{background-color:var(--color-amber-600)}.bg-amber-700{background-color:var(--color-amber-700)}.bg-amber-900\/30{background-color:#7b33064d}@supports (color:color-mix(in lab,red,red)){.bg-amber-900\/30{background-color:color-mix(in oklab,var(--color-amber-900) 30%,transparent)}}.bg-amber-900\/50{background-color:#7b330680}@supports (color:color-mix(in lab,red,red)){.bg-amber-900\/50{background-color:color-mix(in oklab,var(--color-amber-900) 50%,transparent)}}.bg-amber-950\/20{background-color:#46190133}@supports (color:color-mix(in lab,red,red)){.bg-amber-950\/20{background-color:color-mix(in oklab,var(--color-amber-950) 20%,transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\/20{background-color:#0003}@supports (color:color-mix(in lab,red,red)){.bg-black\/20{background-color:color-mix(in oklab,var(--color-black) 20%,transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.bg-black\/70{background-color:#000000b3}@supports (color:color-mix(in lab,red,red)){.bg-black\/70{background-color:color-mix(in oklab,var(--color-black) 70%,transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.bg-black\/80{background-color:color-mix(in oklab,var(--color-black) 80%,transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500) 10%,transparent)}}.bg-blue-500\/15{background-color:#3080ff26}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/15{background-color:color-mix(in oklab,var(--color-blue-500) 15%,transparent)}}.bg-blue-500\/20{background-color:#3080ff33}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/20{background-color:color-mix(in oklab,var(--color-blue-500) 20%,transparent)}}.bg-blue-700{background-color:var(--color-blue-700)}.bg-blue-900\/30{background-color:#1c398e4d}@supports (color:color-mix(in lab,red,red)){.bg-blue-900\/30{background-color:color-mix(in oklab,var(--color-blue-900) 30%,transparent)}}.bg-blue-900\/40{background-color:#1c398e66}@supports (color:color-mix(in lab,red,red)){.bg-blue-900\/40{background-color:color-mix(in oklab,var(--color-blue-900) 40%,transparent)}}.bg-blue-900\/50{background-color:#1c398e80}@supports (color:color-mix(in lab,red,red)){.bg-blue-900\/50{background-color:color-mix(in oklab,var(--color-blue-900) 50%,transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-500\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/15{background-color:color-mix(in oklab,var(--color-emerald-500) 15%,transparent)}}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500) 20%,transparent)}}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-emerald-700{background-color:var(--color-emerald-700)}.bg-emerald-800{background-color:var(--color-emerald-800)}.bg-emerald-900\/30{background-color:#004e3b4d}@supports (color:color-mix(in lab,red,red)){.bg-emerald-900\/30{background-color:color-mix(in oklab,var(--color-emerald-900) 30%,transparent)}}.bg-emerald-900\/40{background-color:#004e3b66}@supports (color:color-mix(in lab,red,red)){.bg-emerald-900\/40{background-color:color-mix(in oklab,var(--color-emerald-900) 40%,transparent)}}.bg-emerald-900\/50{background-color:#004e3b80}@supports (color:color-mix(in lab,red,red)){.bg-emerald-900\/50{background-color:color-mix(in oklab,var(--color-emerald-900) 50%,transparent)}}.bg-emerald-950\/20{background-color:#002c2233}@supports (color:color-mix(in lab,red,red)){.bg-emerald-950\/20{background-color:color-mix(in oklab,var(--color-emerald-950) 20%,transparent)}}.bg-emerald-950\/40{background-color:#002c2266}@supports (color:color-mix(in lab,red,red)){.bg-emerald-950\/40{background-color:color-mix(in oklab,var(--color-emerald-950) 40%,transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\/10{background-color:#00c7581a}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/10{background-color:color-mix(in oklab,var(--color-green-500) 10%,transparent)}}.bg-orange-500{background-color:var(--color-orange-500)}.bg-orange-600{background-color:var(--color-orange-600)}.bg-orange-700{background-color:var(--color-orange-700)}.bg-purple-900\/30{background-color:#59168b4d}@supports (color:color-mix(in lab,red,red)){.bg-purple-900\/30{background-color:color-mix(in oklab,var(--color-purple-900) 30%,transparent)}}.bg-purple-900\/40{background-color:#59168b66}@supports (color:color-mix(in lab,red,red)){.bg-purple-900\/40{background-color:color-mix(in oklab,var(--color-purple-900) 40%,transparent)}}.bg-purple-900\/50{background-color:#59168b80}@supports (color:color-mix(in lab,red,red)){.bg-purple-900\/50{background-color:color-mix(in oklab,var(--color-purple-900) 50%,transparent)}}.bg-purple-950\/20{background-color:#3c036633}@supports (color:color-mix(in lab,red,red)){.bg-purple-950\/20{background-color:color-mix(in oklab,var(--color-purple-950) 20%,transparent)}}.bg-purple-950\/40{background-color:#3c036666}@supports (color:color-mix(in lab,red,red)){.bg-purple-950\/40{background-color:color-mix(in oklab,var(--color-purple-950) 40%,transparent)}}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/10{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.bg-red-500\/15{background-color:#fb2c3626}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/15{background-color:color-mix(in oklab,var(--color-red-500) 15%,transparent)}}.bg-red-600{background-color:var(--color-red-600)}.bg-red-700{background-color:var(--color-red-700)}.bg-red-700\/80{background-color:#bf000fcc}@supports (color:color-mix(in lab,red,red)){.bg-red-700\/80{background-color:color-mix(in oklab,var(--color-red-700) 80%,transparent)}}.bg-red-800{background-color:var(--color-red-800)}.bg-red-900\/30{background-color:#82181a4d}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/30{background-color:color-mix(in oklab,var(--color-red-900) 30%,transparent)}}.bg-red-900\/50{background-color:#82181a80}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/50{background-color:color-mix(in oklab,var(--color-red-900) 50%,transparent)}}.bg-red-950\/40{background-color:#46080966}@supports (color:color-mix(in lab,red,red)){.bg-red-950\/40{background-color:color-mix(in oklab,var(--color-red-950) 40%,transparent)}}.bg-sky-700{background-color:var(--color-sky-700)}.bg-sky-950\/20{background-color:#052f4a33}@supports (color:color-mix(in lab,red,red)){.bg-sky-950\/20{background-color:color-mix(in oklab,var(--color-sky-950) 20%,transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-teal-500\/15{background-color:#00baa726}@supports (color:color-mix(in lab,red,red)){.bg-teal-500\/15{background-color:color-mix(in oklab,var(--color-teal-500) 15%,transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.bg-white\/10{background-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-yellow-400{background-color:var(--color-yellow-400)}.bg-yellow-500{background-color:var(--color-yellow-500)}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-400{background-color:var(--color-zinc-400)}.bg-zinc-500{background-color:var(--color-zinc-500)}.bg-zinc-600{background-color:var(--color-zinc-600)}.bg-zinc-700{background-color:var(--color-zinc-700)}.bg-zinc-800{background-color:var(--color-zinc-800)}.bg-zinc-800\/40{background-color:#27272a66}@supports (color:color-mix(in lab,red,red)){.bg-zinc-800\/40{background-color:color-mix(in oklab,var(--color-zinc-800) 40%,transparent)}}.bg-zinc-900\/40{background-color:#18181b66}@supports (color:color-mix(in lab,red,red)){.bg-zinc-900\/40{background-color:color-mix(in oklab,var(--color-zinc-900) 40%,transparent)}}.bg-zinc-950\/40{background-color:#09090b66}@supports (color:color-mix(in lab,red,red)){.bg-zinc-950\/40{background-color:color-mix(in oklab,var(--color-zinc-950) 40%,transparent)}}.fill-amber-400{fill:var(--color-amber-400)}.fill-current{fill:currentColor}.fill-zinc-500{fill:var(--color-zinc-500)}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.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)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-10{padding:calc(var(--spacing) * 10)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.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-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.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-8{padding-block:calc(var(--spacing) * 8)}.py-px{padding-block:1px}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-\[15vh\]{padding-top:15vh}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pr-6{padding-right:calc(var(--spacing) * 6)}.pr-7{padding-right:calc(var(--spacing) * 7)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-1{padding-left:calc(var(--spacing) * 1)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-7{padding-left:calc(var(--spacing) * 7)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.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-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.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-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-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[var\(--accent-foreground\)\]{color:var(--accent-foreground)}.text-\[var\(--background\)\]{color:var(--background)}.text-\[var\(--destructive\)\]{color:var(--destructive)}.text-\[var\(--foreground\)\],.text-\[var\(--foreground\)\]\/80{color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.text-\[var\(--foreground\)\]\/80{color:color-mix(in oklab,var(--foreground) 80%,transparent)}}.text-\[var\(--muted-foreground\)\],.text-\[var\(--muted-foreground\)\]\/40{color:var(--muted-foreground)}@supports (color:color-mix(in lab,red,red)){.text-\[var\(--muted-foreground\)\]\/40{color:color-mix(in oklab,var(--muted-foreground) 40%,transparent)}}.text-\[var\(--primary\)\]{color:var(--primary)}.text-\[var\(--primary-foreground\)\]{color:var(--primary-foreground)}.text-\[var\(--secondary-foreground\)\]{color:var(--secondary-foreground)}.text-amber-50{color:var(--color-amber-50)}.text-amber-300{color:var(--color-amber-300)}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-black{color:var(--color-black)}.text-blue-100{color:var(--color-blue-100)}.text-blue-300{color:var(--color-blue-300)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-cyan-300{color:var(--color-cyan-300)}.text-cyan-400{color:var(--color-cyan-400)}.text-emerald-50{color:var(--color-emerald-50)}.text-emerald-100{color:var(--color-emerald-100)}.text-emerald-300{color:var(--color-emerald-300)}.text-emerald-300\/80{color:#5ee9b5cc}@supports (color:color-mix(in lab,red,red)){.text-emerald-300\/80{color:color-mix(in oklab,var(--color-emerald-300) 80%,transparent)}}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-600{color:var(--color-emerald-600)}.text-green-300{color:var(--color-green-300)}.text-green-400{color:var(--color-green-400)}.text-indigo-300{color:var(--color-indigo-300)}.text-orange-100{color:var(--color-orange-100)}.text-orange-300{color:var(--color-orange-300)}.text-orange-400{color:var(--color-orange-400)}.text-orange-500{color:var(--color-orange-500)}.text-pink-300{color:var(--color-pink-300)}.text-pink-400{color:var(--color-pink-400)}.text-purple-300{color:var(--color-purple-300)}.text-purple-300\/80{color:#d9b3ffcc}@supports (color:color-mix(in lab,red,red)){.text-purple-300\/80{color:color-mix(in oklab,var(--color-purple-300) 80%,transparent)}}.text-purple-400{color:var(--color-purple-400)}.text-purple-400\/60{color:#c07eff99}@supports (color:color-mix(in lab,red,red)){.text-purple-400\/60{color:color-mix(in oklab,var(--color-purple-400) 60%,transparent)}}.text-red-50{color:var(--color-red-50)}.text-red-100{color:var(--color-red-100)}.text-red-200{color:var(--color-red-200)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-sky-50{color:var(--color-sky-50)}.text-sky-300{color:var(--color-sky-300)}.text-slate-100{color:var(--color-slate-100)}.text-teal-300{color:var(--color-teal-300)}.text-white{color:var(--color-white)}.text-white\/60{color:#fff9}@supports (color:color-mix(in lab,red,red)){.text-white\/60{color:color-mix(in oklab,var(--color-white) 60%,transparent)}}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab,red,red)){.text-white\/80{color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.text-yellow-300{color:var(--color-yellow-300)}.text-yellow-400{color:var(--color-yellow-400)}.text-zinc-50{color:var(--color-zinc-50)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-700{color:var(--color-zinc-700)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.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,)}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.placeholder-\[var\(--muted-foreground\)\]::placeholder{color:var(--muted-foreground)}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a)}.shadow,.shadow-2xl{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040)}.shadow-\[inset_0_-1px_0_var\(--border\)\]{--tw-shadow:inset 0 -1px 0 var(--tw-shadow-color,var(--border))}.shadow-\[inset_0_-1px_0_var\(--border\)\],.shadow-lg{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a)}.ring,.ring-1{--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-\[var\(--border\)\]{--tw-ring-color:var(--border)}.ring-\[var\(--primary\)\],.ring-\[var\(--primary\)\]\/30{--tw-ring-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.ring-\[var\(--primary\)\]\/30{--tw-ring-color:color-mix(in oklab,var(--primary) 30%,transparent)}}.ring-amber-400\/30{--tw-ring-color:#fcbb004d}@supports (color:color-mix(in lab,red,red)){.ring-amber-400\/30{--tw-ring-color:color-mix(in oklab,var(--color-amber-400) 30%,transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px)}.blur,.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,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.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-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-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-150{--tw-duration:.15s;transition-duration:.15s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.prose-invert{--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.ring-inset{--tw-ring-inset:inset}@media (hover:hover){.group-hover\:block:is(:where(.group):hover *){display:block}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.odd\:bg-\[var\(--card\)\]\/40:nth-child(odd){background-color:var(--card)}@supports (color:color-mix(in lab,red,red)){.odd\:bg-\[var\(--card\)\]\/40:nth-child(odd){background-color:color-mix(in oklab,var(--card) 40%,transparent)}}.focus-within\:border-\[var\(--primary\)\]:focus-within{border-color:var(--primary)}.focus-within\:ring-1:focus-within{--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)}.focus-within\:ring-\[var\(--primary\)\]:focus-within{--tw-ring-color:var(--primary)}@media (hover:hover){.hover\:h-1:hover{height:calc(var(--spacing) * 1)}.hover\:w-1:hover{width:calc(var(--spacing) * 1)}.hover\:border-\[var\(--foreground\)\]:hover{border-color:var(--foreground)}.hover\:border-\[var\(--primary\)\]:hover{border-color:var(--primary)}.hover\:bg-\[\#1a1a1a\]\/50:hover{background-color:oklab(21.7786% -7.45058e-9 0/.5)}.hover\:bg-\[var\(--accent\)\]:hover{background-color:var(--accent)}.hover\:bg-\[var\(--destructive\)\]\/20:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--destructive\)\]\/20:hover{background-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}.hover\:bg-\[var\(--muted\)\]\/50:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--muted\)\]\/50:hover{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.hover\:bg-\[var\(--primary\)\]:hover,.hover\:bg-\[var\(--primary\)\]\/20:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--primary\)\]\/20:hover{background-color:color-mix(in oklab,var(--primary) 20%,transparent)}}.hover\:bg-\[var\(--secondary\)\]:hover,.hover\:bg-\[var\(--secondary\)\]\/40:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--secondary\)\]\/40:hover{background-color:color-mix(in oklab,var(--secondary) 40%,transparent)}}.hover\:bg-\[var\(--secondary\)\]\/50:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--secondary\)\]\/50:hover{background-color:color-mix(in oklab,var(--secondary) 50%,transparent)}}.hover\:bg-\[var\(--secondary\)\]\/60:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--secondary\)\]\/60:hover{background-color:color-mix(in oklab,var(--secondary) 60%,transparent)}}.hover\:bg-\[var\(--secondary\)\]\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-\[var\(--secondary\)\]\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-emerald-500:hover{background-color:var(--color-emerald-500)}.hover\:bg-emerald-600:hover{background-color:var(--color-emerald-600)}.hover\:bg-green-500\/20:hover{background-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.hover\:bg-green-500\/20:hover{background-color:color-mix(in oklab,var(--color-green-500) 20%,transparent)}}.hover\:bg-orange-700:hover{background-color:var(--color-orange-700)}.hover\:bg-purple-900\/20:hover{background-color:#59168b33}@supports (color:color-mix(in lab,red,red)){.hover\:bg-purple-900\/20:hover{background-color:color-mix(in oklab,var(--color-purple-900) 20%,transparent)}}.hover\:bg-purple-900\/30:hover{background-color:#59168b4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-purple-900\/30:hover{background-color:color-mix(in oklab,var(--color-purple-900) 30%,transparent)}}.hover\:bg-red-500:hover{background-color:var(--color-red-500)}.hover\:bg-red-500\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/10:hover{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.hover\:bg-red-500\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/20:hover{background-color:color-mix(in oklab,var(--color-red-500) 20%,transparent)}}.hover\:bg-red-500\/25:hover{background-color:#fb2c3640}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/25:hover{background-color:color-mix(in oklab,var(--color-red-500) 25%,transparent)}}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-red-700\/80:hover{background-color:#bf000fcc}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-700\/80:hover{background-color:color-mix(in oklab,var(--color-red-700) 80%,transparent)}}.hover\:bg-sky-600:hover{background-color:var(--color-sky-600)}.hover\:bg-white\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/10:hover{background-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab,var(--color-white) 20%,transparent)}}.hover\:bg-zinc-600:hover{background-color:var(--color-zinc-600)}.hover\:bg-zinc-700:hover{background-color:var(--color-zinc-700)}.hover\:text-\[var\(--foreground\)\]:hover{color:var(--foreground)}.hover\:text-\[var\(--primary\)\]:hover{color:var(--primary)}.hover\:text-amber-200:hover{color:var(--color-amber-200)}.hover\:text-blue-300:hover{color:var(--color-blue-300)}.hover\:text-blue-400:hover{color:var(--color-blue-400)}.hover\:text-green-300:hover{color:var(--color-green-300)}.hover\:text-red-300:hover{color:var(--color-red-300)}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:text-white:hover{color:var(--color-white)}.hover\:text-zinc-300:hover{color:var(--color-zinc-300)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:ring-1:hover{--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)}.hover\:ring-\[var\(--primary\)\]\/40:hover{--tw-ring-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:ring-\[var\(--primary\)\]\/40:hover{--tw-ring-color:color-mix(in oklab,var(--primary) 40%,transparent)}}}.focus\:border-\[var\(--primary\)\]:focus{border-color:var(--primary)}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:ring-1:focus{--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)}.focus\:ring-\[var\(--primary\)\]:focus{--tw-ring-color:var(--primary)}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}}.prose-headings\:my-2 :where(h1,h2,h3,h4,h5,h6,th):not(:where([class~=not-prose],[class~=not-prose] *)){margin-block:calc(var(--spacing) * 2)}.prose-headings\:scroll-mt-4 :where(h1,h2,h3,h4,h5,h6,th):not(:where([class~=not-prose],[class~=not-prose] *)){scroll-margin-top:calc(var(--spacing) * 4)}.prose-headings\:font-semibold :where(h1,h2,h3,h4,h5,h6,th):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.prose-headings\:text-\[var\(--foreground\)\] :where(h1,h2,h3,h4,h5,h6,th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-h1\:border-b :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.prose-h1\:border-\[var\(--border\)\] :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}.prose-h1\:pb-2 :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){padding-bottom:calc(var(--spacing) * 2)}.prose-h1\:text-2xl :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.prose-h2\:border-b :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.prose-h2\:border-\[var\(--border\)\] :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}.prose-h2\:pb-1\.5 :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){padding-bottom:calc(var(--spacing) * 1.5)}.prose-h2\:text-xl :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.prose-h3\:text-lg :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.prose-p\:my-1\.5 :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-block:calc(var(--spacing) * 1.5)}.prose-p\:leading-relaxed :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.prose-p\:text-\[var\(--foreground\)\] :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-a\:text-\[var\(--primary\)\] :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--primary)}.prose-a\:text-blue-400 :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--color-blue-400)}.prose-a\:no-underline :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-line:none}@media (hover:hover){.hover\:prose-a\:underline:hover :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-line:underline}}.prose-blockquote\:border-l-blue-500 :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){border-left-color:var(--color-blue-500)}.prose-blockquote\:text-\[var\(--muted-foreground\)\] :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--muted-foreground)}.prose-strong\:text-\[var\(--foreground\)\] :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-code\:rounded :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:.25rem}.prose-code\:bg-\[var\(--secondary\)\] :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:var(--secondary)}.prose-code\:px-1 :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 1)}.prose-code\:px-1\.5 :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 1.5)}.prose-code\:py-0\.5 :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){padding-block:calc(var(--spacing) * .5)}.prose-code\:text-xs :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.prose-code\:text-amber-300 :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--color-amber-300)}.prose-code\:after\:content-none :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after,.prose-code\:before\:content-none :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:var(--tw-content);--tw-content:none;content:none}.prose-pre\:my-2 :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){margin-block:calc(var(--spacing) * 2)}.prose-pre\:rounded-lg :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:var(--radius-lg)}.prose-pre\:border :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){border-style:var(--tw-border-style);border-width:1px}.prose-pre\:border-\[var\(--border\)\] :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}.prose-pre\:bg-\[var\(--secondary\)\] :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:var(--secondary)}.prose-ol\:my-1\.5 :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-ul\:my-1\.5 :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-block:calc(var(--spacing) * 1.5)}.prose-li\:my-0\.5 :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-block:calc(var(--spacing) * .5)}.prose-li\:text-\[var\(--foreground\)\] :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-table\:border-collapse :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){border-collapse:collapse}.prose-th\:border :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){border-style:var(--tw-border-style);border-width:1px}.prose-th\:border-\[var\(--border\)\] :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}.prose-th\:bg-\[var\(--secondary\)\] :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:var(--secondary)}.prose-th\:px-2 :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 2)}.prose-th\:px-3 :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 3)}.prose-th\:py-1 :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-block:calc(var(--spacing) * 1)}.prose-th\:py-1\.5 :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-block:calc(var(--spacing) * 1.5)}.prose-th\:text-\[var\(--foreground\)\] :where(th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-td\:border :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){border-style:var(--tw-border-style);border-width:1px}.prose-td\:border-\[var\(--border\)\] :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}.prose-td\:px-2 :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 2)}.prose-td\:px-3 :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline:calc(var(--spacing) * 3)}.prose-td\:py-1 :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-block:calc(var(--spacing) * 1)}.prose-td\:py-1\.5 :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-block:calc(var(--spacing) * 1.5)}.prose-td\:text-\[var\(--foreground\)\] :where(td):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--foreground)}.prose-img\:rounded-lg :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){border-radius:var(--radius-lg)}.prose-hr\:border-\[var\(--border\)\] :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--border)}}:root{--background:#0a0a0a;--foreground:#ededed;--card:#141414;--card-foreground:#ededed;--border:#2a2a2a;--input:#2a2a2a;--primary:#3b82f6;--primary-foreground:#fff;--secondary:#1e1e1e;--secondary-foreground:#a1a1a1;--muted:#1e1e1e;--muted-foreground:#737373;--accent:#1e293b;--accent-foreground:#e2e8f0;--destructive:#ef4444;--ring:#3b82f6;--radius:.5rem}*{border-color:var(--border)}body{background:var(--background);color:var(--foreground)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:#333;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#555}[data-panel-resize-handle-id]{background:var(--border);transition:background .15s}[data-panel-resize-handle-id]:hover,[data-panel-resize-handle-id][data-resize-handle-active]{background:var(--primary)}@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-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@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-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(1turn)}}@keyframes pulse{50%{opacity:.5}}
@@ -1,362 +0,0 @@
1
- # Cron Tasks
2
-
3
- Global, cross-workspace scheduled agent runs. The user defines a job
4
- (workspace + agent + prompt + schedule + channel targets); the server
5
- schedules it via croner; on fire, a `halo cli` child runs the prompt;
6
- the captured stdout is fanned out to the bound channels and the run is
7
- recorded in an audit log.
8
-
9
- Two trigger modes:
10
-
11
- - **Recurring** — standard 5-field cron expression; fires on every match.
12
- - **One-shot (at-mode)** — exact instant via `runAt` (epoch ms); fires
13
- once at that time, then auto-disables (the row is kept for history /
14
- rerun, but `enabled=0` so reload doesn't re-instantiate the schedule).
15
- Same shape as `at(1)`. Picked when the user says "remind me at 3pm",
16
- "send the report next Monday" — anything that doesn't repeat.
17
-
18
- ## Goal
19
-
20
- Enable scheduled agent work — daily reports, periodic monitoring digests,
21
- one-off reminders, scheduled data refreshes — without leaving a session
22
- open or wiring external schedulers (cron, systemd timers, etc.).
23
-
24
- Non-goals:
25
-
26
- - **One-off ad-hoc invocations bound to "fresh state" per fire.** Each
27
- job has a stable `cron-<jobId>` session id; first fire creates it,
28
- subsequent fires resume it. So history accumulates over time and the
29
- user can review the full conversation in the admin Sessions tab.
30
- Threading via `-s cron-<jobId>` lets the agent remember what it told
31
- the channel last week without each prompt needing to bootstrap from
32
- `.halo/memory/`.
33
- - **Conditional / event-driven triggers.** Only time-based scheduling.
34
- - **Cross-job orchestration.** Each job is independent.
35
-
36
- ## Components
37
-
38
- ### Storage
39
-
40
- `~/.halo/global/cron.db` (sqlite + drizzle, parallel to `evo.db`).
41
-
42
- ```sql
43
- cron_jobs(
44
- id TEXT PRIMARY KEY,
45
- label TEXT, -- nullable
46
- workspace_path TEXT NOT NULL,
47
- agent_id TEXT NOT NULL,
48
- user_prompt TEXT NOT NULL,
49
- schedule TEXT NOT NULL, -- 5-field cron; '' for at-mode
50
- run_at INTEGER, -- one-shot fire time (epoch ms);
51
- -- mutually exclusive with `schedule`
52
- timezone TEXT, -- IANA zone, null = host TZ
53
- targets TEXT NOT NULL -- JSON array of
54
- -- {channelType, accountId, chatId?}
55
- DEFAULT '[]',
56
- enabled INTEGER NOT NULL DEFAULT 1,
57
- last_run_status TEXT, -- runner-managed cache
58
- last_run_at INTEGER,
59
- last_run_id TEXT,
60
- created_at INTEGER NOT NULL,
61
- updated_at INTEGER NOT NULL
62
- )
63
-
64
- cron_runs(
65
- id TEXT PRIMARY KEY,
66
- job_id TEXT NOT NULL,
67
- trigger_kind TEXT NOT NULL, -- 'scheduled' | 'manual'
68
- status TEXT NOT NULL, -- running | succeeded | failed | timeout
69
- started_at INTEGER NOT NULL,
70
- completed_at INTEGER,
71
- output TEXT, -- final cli stdout
72
- exit_code INTEGER,
73
- failure_reason TEXT,
74
- log_path TEXT, -- absolute path to per-run log file
75
- dispatch_results TEXT -- JSON array of per-recipient outcomes
76
- -- {channelType, accountId, chatId?, ok, error?}
77
- )
78
- ```
79
-
80
- `run_at` is added in-place to pre-existing dbs via a `PRAGMA table_info`
81
- guard in `createCronDb` (idempotent ALTER) — no manual migration step.
82
-
83
- Per-target `chatId` pins delivery to a specific conversation. For
84
- **telegram / slack / feishu** it is required — the dispatchers reject
85
- targets without one (the old "fan out to allowedUsers" / "fall back to
86
- lastActiveChatId" behaviour was removed because in practice the most-
87
- recent inbound was rarely the cron creator, and the result kept landing
88
- in a stranger's chat). For **wechat** it stays optional — wechat has a
89
- QR-bound owner so single-recipient delivery has an obvious target.
90
-
91
- Cron jobs created from inside a chat via the `manage-cron-jobs` skill auto-pin
92
- the originating `chatId` (the channel context exposes it as
93
- `{{channel.chat_id}}`). Admin-UI cron jobs that don't specify a chatId
94
- for tg/slack/feishu run silently — the result shows in the cron log,
95
- nothing is pushed.
96
-
97
- Why a separate db: same reasoning as `evo.db` — global, cross-workspace
98
- state shouldn't live inside any one workspace's `.halo/`. The runner
99
- itself is workspace-agnostic.
100
-
101
- ### Runner — `packages/server/src/cron/runner.ts`
102
-
103
- Boot path:
104
- 1. `startCronDaemon()` is called from server `index.ts` after
105
- `setCronDb(...)`.
106
- 2. Reads every `enabled=1` row, instantiates a croner schedule per job.
107
- - Recurring rows: `new Cron(job.schedule, { timezone }, fn)`.
108
- - One-shot rows (`runAt` set): `new Cron(new Date(job.runAt), …, fn)`.
109
- croner accepts a `Date` and self-stops after firing once. Past-due
110
- `runAt` is logged and skipped — the user can still fire via run-now.
111
- 3. Starts two timers:
112
- - `pruneOldLogs` — daily, drops log files past 30-day retention and
113
- `cron_runs` rows past 60 days.
114
- - `reconcileFromDb` — every 10 seconds, syncs the in-memory schedule
115
- map against db rows. Detects adds / removes / schedule / runAt /
116
- timezone / enabled changes and patches the croner instances
117
- accordingly. Cheap (small table) and covers out-of-band edits (the
118
- `manage-cron-jobs` skill writes via `sqlite3` rather than the REST
119
- API). Per-row fingerprint = `enabled|schedule|runAt|timezone`.
120
-
121
- When a fire happens:
122
- 1. `runJob(jobId, 'scheduled')` writes a `cron_runs` row with
123
- `status='running'`.
124
- 2. Spawns `halo cli -a <agentId> -s cron-<jobId> -w <workspacePath>` with
125
- the prompt piped on **stdin** (not argv — a long prompt would overflow the
126
- Windows command-line limit). A Node timer kills the child after
127
- `CLI_TIMEOUT_SEC` and reports exit 124 — same contract as the Linux-only
128
- `timeout(1)` binary, but cross-platform.
129
- On Windows `resolveHaloCli()` returns `halo.cmd` (not bare `halo`):
130
- the desktop installer drops `halo.cmd` and `Halo.exe` into the same
131
- dir on PATH, and PATHEXT ranks `.EXE` above `.CMD`, so a bare `halo`
132
- would launch the GUI instead of the cli. Spawning a `.cmd` directly is
133
- rejected by Node ≥21.7 (EINVAL), so the child is routed through
134
- `cmd.exe /c` on Windows.
135
- On **macOS** bare `halo` resolves via PATH to the `/usr/local/bin`
136
- launcher, but a Finder/Dock-launched desktop app has only launchd's
137
- minimal PATH — so the Electron main process prepends the standard CLI
138
- dirs to the server child's `env.PATH` (see `dev/desktop-packaging.md`),
139
- otherwise this spawn would `ENOENT`.
140
- The `-s` flag uses **create-on-missing semantics** (added alongside
141
- cron): if the session id already exists in `agent_sessions`, cli
142
- resumes it; if not, cli creates a new row with that exact id. So the
143
- first fire bootstraps the session, every subsequent fire continues
144
- the same conversation, and the user can review history in the admin
145
- Sessions tab. The `cron-<jobId>` prefix avoids collision with normal
146
- `cli_*` / `tg_*` / `wx_*` ids.
147
- Same shape as the evo wrapper (`spawn` + tee'd stdout/stderr to
148
- `~/.halo/global/logs/cron/<runId>.log`).
149
- 3. On exit:
150
- - Exit 0 + non-empty stdout → `succeeded`, dispatch the trimmed
151
- stdout to every target.
152
- - Exit 124 → `timeout`.
153
- - Anything else → `failed` with stderr tail as `failure_reason`.
154
- - Empty output on exit 0 → `failed: cli produced no output`.
155
- 4. If every target's dispatch failed, downgrade the run status to
156
- `failed` so the UI surfaces the issue (and so a job that always
157
- times-out on telegram doesn't keep showing green).
158
- 5. **At-mode auto-disable.** `finalize` looks up the row; when `runAt`
159
- is set, it patches `enabled=0` alongside the lastRunStatus update.
160
- Reconcile then tears down the croner instance on its next pass.
161
- The row is kept (so the admin UI shows it under run history; user
162
- can still hit run-now to refire).
163
-
164
- ### Dispatcher — `packages/server/src/cron/dispatcher.ts` (registry)
165
-
166
- The dispatcher is **channel-agnostic**. It exposes a tiny registry
167
- (`registerCronDispatcher`) and a single fan-out entry-point
168
- (`dispatchToTargets`); each channel module supplies its own
169
- `CronChannelDispatcher` and registers it at server boot. There is no
170
- switch-on-channelType anywhere in `cron/`.
171
-
172
- ```ts
173
- interface CronChannelDispatcher {
174
- channelType: string
175
- dispatch: (accountId: string, text: string, chatId?: string) => Promise<DispatchResult[]>
176
- listTargets?: () => CronTargetOption[] // for admin UI dropdown
177
- }
178
- ```
179
-
180
- `dispatch` returns one `DispatchResult` row per recipient. Today every
181
- channel is single-recipient (one explicit chatId → one row), but the
182
- array shape is preserved so a future channel that supports broadcast
183
- could return N. Throwing wraps into a single failed-result.
184
-
185
- Channel modules:
186
-
187
- - `packages/server/src/channels/telegram/cron-dispatcher.ts` —
188
- `registerTelegramCronDispatcher()`. Requires explicit numeric `chatId`;
189
- errors otherwise. (Previous build fanned out to `allowedUsers` and fell
190
- back to `lastActiveChatId`; both removed because cron output kept
191
- landing in unrelated chats.)
192
- - `packages/server/src/channels/wechat/cron-dispatcher.ts` —
193
- `registerWechatCronDispatcher()`. Single-recipient with chained
194
- fallback: explicit `chatId` → account `userId` (QR-bind owner) →
195
- cached `lastActiveChatId`. WeChat keeps the fallback because the
196
- QR-bound owner is a stable, unambiguous target.
197
- - `packages/server/src/channels/slack/cron-dispatcher.ts` —
198
- `registerSlackCronDispatcher()`. Requires explicit `chatId` shaped as
199
- `D…` (DM), `C…` (channel top-level), or `C…:<thread_ts>` (anchored
200
- inside a thread). Posts via `postMessage` with `thread_ts` set when
201
- present.
202
- - `packages/server/src/channels/feishu/cron-dispatcher.ts` —
203
- `registerFeishuCronDispatcher()`. Requires explicit `chatId` shaped as
204
- `oc_…`. Posts via the v1 messages API with `receive_id_type=chat_id`.
205
- (A `:rootId` suffix is accepted in the storage shape for forward-compat
206
- but currently ignored — Feishu's open API has no thread-anchored
207
- sendMessage path analogous to Slack's `thread_ts`.)
208
-
209
- Both register at server boot in `index.ts`. **Adding a new channel = ship
210
- a `cron-dispatcher.ts` next to its handler + register it once.** Nothing
211
- in `cron/` or `routes/cron.ts` needs to change.
212
-
213
- `listTargets()` per channel feeds the admin UI's create-form dropdown
214
- via `listAllCronTargets()` (aggregator). `ready` flag: wechat = QR-bind
215
- userId OR cached lastActiveChatId; telegram / slack / feishu always
216
- report `ready=true` (readiness depends on the per-target `chatId` the
217
- admin picks, not on prior inbound history). The admin form has a
218
- per-target chatId input + search dropdown for slack/feishu, backed by
219
- `users.conversations` / `/im/v1/chats`. Channels with no UI-pickable
220
- surface (a hypothetical webhook channel) can omit `listTargets`.
221
-
222
- `DispatchResult` shape:
223
-
224
- ```ts
225
- { channelType, accountId, chatId?, ok, error? }
226
- ```
227
-
228
- `chatId` is recorded so the admin UI can render per-recipient outcomes
229
- ("slack:T01234/D012345 ✓ · feishu:appA/oc_xxx ✗ (no permission)") when a
230
- job has multiple targets, instead of just a single ok/fail roll-up.
231
-
232
- ### Realtime updates — WS broadcast (no client polling)
233
-
234
- The admin UI subscribes to `cron:job_changed` and `cron:run_changed`
235
- events on the existing `/ws` channel rather than polling on a timer.
236
- Server emits them at every state-change point:
237
-
238
- - `runner.runJob` insert of the `running` cron_runs row →
239
- `cron:run_changed status='running'`
240
- - `runner.finalize` (success/failure/timeout) →
241
- `cron:run_changed status='succeeded'|'failed'|'timeout'` plus a
242
- `cron:job_changed` so the list's "last run" badge updates
243
- - REST routes (POST/PUT/DELETE on `/cron/jobs[/:id]`) →
244
- `cron:job_changed kind='created'|'updated'|'deleted'`
245
-
246
- Broadcast is fan-out via `ws/broadcast.ts` to every connected admin
247
- socket. Idle traffic is ~zero.
248
-
249
- ### REST routes — `packages/server/src/routes/cron.ts`
250
-
251
- Standard CRUD over `cron_jobs` plus:
252
-
253
- - `POST /api/cron/jobs/:id/run-now` — fire-and-forget; returns
254
- immediately, run status flips broadcast as cron:run_changed events.
255
- - `GET /api/cron/jobs/:id/runs?limit=N&before=<runId>` — cursor-paged
256
- history. `runId` is `<isoTimestamp>-<slug>`, so its lexicographic
257
- order matches time — `id < cursor` gives "older than" without a
258
- numeric sequence column. Response: `{ runs, hasMore, nextCursor }`.
259
- - `GET /api/cron/runs/:runId/log` — raw log content (or null if past
260
- retention).
261
- - `GET /api/cron/channel-targets` — the create-form's list of bindable
262
- channel accounts. Aggregated from the registry via
263
- `listAllCronTargets()` — routes/cron.ts is channel-agnostic. `ready`
264
- flag is computed inside each channel's `listTargets()` (see
265
- "Dispatcher" above for the per-channel rules).
266
- - `POST /api/cron/reload` — force re-read all schedules. Rarely needed
267
- (reconcile already polls); useful after manual db edits if you don't
268
- want to wait 10 seconds.
269
-
270
- All routes go through the standard auth middleware — same cookie/token
271
- as the rest of `/api`.
272
-
273
- ### Agent skill — `templates/skills/manage-cron-jobs/`
274
-
275
- Registered in `init.ts`'s `BUILTIN_SKILL_IDS`. Frontmatter has
276
- `requiresAccess: full`, so readonly / workspace channels (like a
277
- public-facing telegram bot) can't see or invoke this skill — only
278
- admin-shell agents can. The skill ships with a `manage-cron.py` helper
279
- that the agent calls via `shell_exec`; the script handles id
280
- generation, target JSON encoding, and timestamps so the agent isn't
281
- hand-crafting SQL.
282
-
283
- The runner's reconcile loop picks up db changes within ~10 seconds and
284
- broadcasts `cron:job_changed { kind: 'reconciled' | 'deleted' }` so
285
- admin UIs in another tab/browser see the same edit. The skill doesn't
286
- need REST/auth — it's filesystem + sqlite, with the in-process runner
287
- catching up on its own pace.
288
-
289
- The skill walks the agent through:
290
- 1. Identifying user intent (list / create / edit / delete).
291
- 2. Defaulting workspace (current), agent (`default`), targets (current
292
- chat when invoked from a channel — see channel context below).
293
- 3. Translating spoken-time → 5-field cron (recurring) **or** ISO-8601
294
- instant (`--run-at`, one-shot at-mode).
295
- 4. Querying `channels.db` for available targets and surfacing
296
- readiness warnings (currently only wechat can be `ready=false`).
297
- 5. Writing the appropriate INSERT/UPDATE/DELETE.
298
-
299
- **Channel context at skill invocation.** When the user triggers the
300
- `manage-cron-jobs` skill from inside a telegram / wechat / slack / feishu
301
- chat, the channel handler injects structured origin into the skill's
302
- render context as built-in placeholders: `{{channel.type}}`,
303
- `{{channel.account_id}}`, `{{channel.chat_id}}`. The skill body uses
304
- these to default the `--targets` flag to `<type>:<account_id>:<chat_id>`
305
- so the schedule keeps replying in the same conversation. Admin/WS
306
- invocations leave the placeholders empty — the skill then either asks
307
- for an explicit chatId or accepts a silent (no-target) cron.
308
-
309
- **Reverse-lookup by chatId.** Inside a chat the user doesn't know the
310
- cron `id` ("delete the daily digest I set up here"). The helper script
311
- exposes `list --chat-id <id>` that filters `cron_jobs` to those whose
312
- `targets[].chatId` matches. The skill uses
313
- `list --chat-id {{channel.chat_id}}` to find candidate jobs, confirms
314
- with the user, then deletes by id. Different channels' chatId formats
315
- don't collide (telegram numeric, slack `D…/C…`, feishu `oc_…`,
316
- wechat `o…`), so a single chatId match is unambiguous across channels.
317
-
318
- ### Admin UI — `packages/admin/src/features/cron/cron-main.tsx`
319
-
320
- Activity-bar entry next to Evolution. Two-pane layout matching
321
- Evolution's: list of jobs on the left, detail panel on the right with
322
- run history and edit/run-now/delete actions. Form supports both create
323
- and edit. Form pulls workspace + agent + channel-target options from
324
- existing APIs (`/api/agent-configs`, `/api/cron/channel-targets`).
325
-
326
- ## Boot
327
-
328
- `packages/server/src/index.ts`:
329
- ```ts
330
- setChannelDb(channelDb) // for dispatcher's getChannelDb()
331
- setCronDb(createCronDb(path.join(HALO_HOME, 'global')))
332
- // `bootChannels` walks `defaultChannelDescriptors` and calls each
333
- // descriptor's `registerCronDispatcher` (alongside its handler/route
334
- // setup). Order is irrelevant — the registry is keyed by channelType.
335
- bootChannels(app, defaultChannelDescriptors, { registry, db: channelDb })
336
- // Daemon starts after channels boot so the registry is fully populated
337
- // before the first scheduled fire.
338
- startCronDaemon()
339
- ```
340
-
341
- `packages/server/src/init.ts` `BUILTIN_SKILL_IDS` includes
342
- `manage-cron-jobs` so `halo setup` deploys the skill.
343
-
344
- ## Known limits
345
-
346
- - **No mid-run heartbeat.** If the server crashes between the
347
- `cron_runs.insert(status='running')` and the cli exit handler, the row
348
- is stranded in `running`. (Evo handles this via heartbeat + ticker
349
- recovery.) For cron, runs are short (<10 minutes by `timeout`) and
350
- infrequent; we accept the rough edge for now. Fix: add a daily
351
- scanner that flips stale-running rows to `failed: server crashed`.
352
- - **Web channel can't deliver.** SSE channel is reactive-only; cron
353
- records a clear failure rather than swallowing.
354
- - **No retry.** Failed runs stay failed; user sees them in history and
355
- decides whether to investigate or wait for the next fire.
356
- - **Single-process scheduler.** Two server instances against the same
357
- global db would both schedule the same jobs. Today there's only ever
358
- one server per host (pid lock); document & enforce when that
359
- assumption ever breaks.
360
- - **`run-now` ignores enabled flag.** A disabled job can still be
361
- fired manually from the UI for testing — the schedule is paused, the
362
- runner code path isn't.