@mediamonks/canopy-cli 0.7.20 → 0.7.22

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 (39) hide show
  1. package/dist/{dev-DtEwiNYi.mjs → dev-CNqx_53I.mjs} +3 -3
  2. package/dist/dev-D7v7WK9O.mjs +2 -0
  3. package/dist/{dev-worker-IWnHvQ1f.mjs → dev-worker-Bij9OUMk.mjs} +1 -1
  4. package/dist/docs/cli-dev.md +1 -1
  5. package/dist/docs/cli-logs.md +1 -1
  6. package/dist/docs/data.md +2 -2
  7. package/dist/docs/dev.md +1 -1
  8. package/dist/docs/developers-architecture.md +26 -18
  9. package/dist/docs/index.json +21 -11
  10. package/dist/docs/migrations.md +17 -14
  11. package/dist/docs/platform-assistant.md +50 -0
  12. package/dist/docs/platform-egress.md +2 -2
  13. package/dist/docs/platform-feedback.md +3 -0
  14. package/dist/docs/{notifications.md → platform-notifications.md} +6 -2
  15. package/dist/docs/platform-project-data.md +3 -3
  16. package/dist/docs/platform-schedules.md +1 -1
  17. package/dist/docs/platform-sites-and-profiles.md +1 -1
  18. package/dist/docs/platform-slack.md +85 -0
  19. package/dist/docs/sdk-files.md +11 -1
  20. package/dist/docs/sdk-slack.md +132 -0
  21. package/dist/docs/static-serving.md +58 -300
  22. package/dist/{docs-C2D7__Iz.mjs → docs-c0CdeBxh.mjs} +1 -1
  23. package/dist/{feedback-BvkCjS-g.mjs → feedback-QhD8k6Ph.mjs} +8 -3
  24. package/dist/index.mjs +10 -10
  25. package/dist/{local-CKRZur_5.mjs → local-CsSP4Vpt.mjs} +2 -2
  26. package/dist/login-BrEDKrb3.mjs +285 -0
  27. package/dist/{package-B-aXVcQu.mjs → package-BuwV_mje.mjs} +1 -1
  28. package/dist/{skill-CqiSkac0.mjs → skill-BvoYCIKk.mjs} +1 -1
  29. package/dist/{src-Bu4Ze32I.mjs → src-BKKAEkbH.mjs} +25 -2
  30. package/dist/templates/spa/package.json +1 -1
  31. package/dist/templates/worker/AGENTS.md +3 -0
  32. package/dist/templates/worker/package.json +1 -1
  33. package/dist/templates/worker/worker/index.ts +20 -3
  34. package/dist/{upgrade-CpUCVTrN.mjs → upgrade-0lmdjvom.mjs} +1 -1
  35. package/dist/{usage-CRpVLLi6.mjs → usage-C1-cvS2-.mjs} +13 -1
  36. package/package.json +2 -2
  37. package/dist/dev-DjkK-50R.mjs +0 -2
  38. package/dist/docs/infrastructure.md +0 -406
  39. package/dist/login-D-Ac_kFW.mjs +0 -285
@@ -1,285 +0,0 @@
1
- import { _ as writeConfigFile, f as clearAllProfileTokens, g as upsertProfileAuth, h as setActiveProfile, m as readConfigFile, n as siteConfig, p as listBakedProfiles, v as getBakedProfile, y as isProfileId } from "./site-BFaWfSVu.mjs";
2
- import { n as openBrowser, r as reportErrors } from "./ui--atbZ-TM.mjs";
3
- import { defineCommand } from "citty";
4
- import * as p from "@clack/prompts";
5
- import { createHash, randomBytes } from "node:crypto";
6
- import { createServer } from "node:http";
7
- //#region ../pages/src/generated/cli-login.ts
8
- const okHtml = "<!doctype html><html lang=\"en\"><head><meta charSet=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>You’re signed in · Canopy</title><style>/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking: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-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-outline-style:solid;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:\"Helvetica Now for Monks\", ui-sans-serif, system-ui, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;--color-red-100:#ffebf0;--color-red-200:#ffd1dd;--color-red-300:#ffa8be;--color-red-400:#ff7a9c;--color-red-500:#ff527d;--color-red-600:#ff245b;--color-red-800:#a30029;--color-red-950:#610018;--color-amber-200:#fde68a;--color-amber-950:#451a03;--color-yellow-100:#fff7db;--color-yellow-900:#7a6000;--color-green-100:#e3fcf1;--color-green-200:#b8fadd;--color-green-900:#067445;--color-green-950:#065533;--color-purple-50:#faf6fd;--color-purple-300:#d6b6f1;--color-purple-400:#c598ec;--color-purple-500:#ac6de3;--color-purple-600:#8c3fd2;--color-purple-700:#7d26c9;--color-purple-900:#501881;--color-gray-800:#5d5d60;--color-neutral-50:#f5f5f4;--color-neutral-100:#e9e8e7;--color-neutral-200:#d6d4d2;--color-neutral-300:#c0beb9;--color-neutral-400:#adaaa4;--color-neutral-500:#97938c;--color-neutral-600:#837f77;--color-neutral-700:#6c6962;--color-neutral-900:#484641;--color-neutral-950:#3e3c38;--color-stone-500:#78716c;--color-stone-600:#57534e;--color-stone-700:#44403c;--color-stone-800:#292524;--color-stone-900:#1c1917;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:12px;--text-xs--line-height:16px;--text-sm:14px;--text-sm--line-height:20px;--text-2xl:24px;--text-2xl--line-height:32px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.01em;--tracking-wide:.015em;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-md:6px;--radius-lg:8px;--radius-xl:12px;--radius-2xl:16px;--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);--color-foreground:var(--foreground);--color-primary:var(--primary);--color-primary-foreground:var(--primary-foreground);--color-muted-foreground:var(--muted-foreground);--color-destructive:var(--destructive);--color-border:var(--border);--color-card:var(--card);--color-brand:var(--brand);--color-brand-foreground:var(--brand-foreground)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root,[data-theme=monks-flow]{--background:var(--color-white);--background-emphasis:var(--color-neutral-900);--foreground:var(--color-neutral-950);--foreground-alt:var(--color-neutral-700);--foreground-subtle:var(--color-neutral-600);--primary:var(--color-neutral-900);--primary-foreground:var(--color-neutral-50);--primary-hover:var(--color-neutral-950);--secondary:#f5f3f0;--secondary-foreground:var(--color-neutral-900);--secondary-hover:#e7e2dc;--muted:var(--color-neutral-100);--muted-foreground:var(--color-neutral-500);--accent:#e7e2dc;--accent-foreground:var(--color-neutral-900);--destructive:#e11d48;--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-100);--destructive-soft-foreground:var(--color-red-800);--ghost:#fff0;--ghost-foreground:var(--color-neutral-700);--ghost-hover:#0000000d;--positive:var(--color-green-100);--positive-foreground:var(--color-green-900);--surface:var(--color-neutral-50);--surface-emphasis:var(--color-neutral-300);--surface-raised:var(--color-neutral-200);--border:var(--color-neutral-200);--border-light:var(--color-neutral-100);--border-lighter:var(--color-neutral-50);--border-strong:var(--color-neutral-400);--input:var(--color-neutral-50);--input-foreground:var(--color-neutral-950);--ring:var(--color-black);--ring-error:var(--color-red-300);--card:var(--color-white);--card-foreground:var(--color-neutral-950);--popover:var(--color-white);--popover-foreground:var(--color-neutral-950);--warning:var(--color-yellow-100);--warning-foreground:var(--color-yellow-900);--chart-1:#f54a00;--chart-2:#009689;--chart-3:#104e64;--chart-4:#ffb900;--chart-5:#fe9a00;--chart-negative:#f54a00;--chart-positive:#009689;--chart-fill:#bfdeffb3;--chart-fill-2:#aaccffb3;--chart-stroke-2:#3f8dff;--sidebar:var(--color-neutral-50);--sidebar-foreground:var(--color-gray-800);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-neutral-200);--sidebar-ring:var(--ring);--backdrop:#0009;--theme-background:#f5f4f2}:root.dark:not([data-theme]),[data-theme=monks-flow].dark,[data-theme=monks-flow] .dark{--background:var(--color-stone-900);--background-emphasis:var(--color-neutral-100);--foreground:var(--color-neutral-50);--foreground-alt:var(--color-neutral-300);--foreground-subtle:var(--color-neutral-400);--primary:var(--color-neutral-50);--primary-foreground:var(--color-black);--primary-hover:var(--color-neutral-100);--secondary:var(--color-stone-700);--secondary-foreground:var(--color-neutral-100);--secondary-hover:var(--color-stone-600);--muted:var(--color-stone-800);--muted-foreground:var(--color-neutral-500);--accent:var(--color-neutral-900);--accent-foreground:var(--color-neutral-300);--destructive:var(--color-red-500);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-950);--destructive-soft-foreground:var(--color-red-200);--ghost:#fff0;--ghost-foreground:var(--color-neutral-300);--ghost-hover:#ffffff14;--positive:var(--color-green-950);--positive-foreground:var(--color-green-200);--surface:var(--color-stone-800);--surface-emphasis:var(--color-stone-600);--surface-raised:var(--color-stone-700);--border:var(--color-stone-600);--border-light:var(--color-stone-700);--border-lighter:var(--color-stone-800);--border-strong:var(--color-stone-500);--input:var(--color-stone-800);--input-foreground:var(--color-neutral-50);--ring:var(--color-white);--ring-error:var(--color-red-400);--card:var(--color-stone-800);--card-foreground:var(--color-neutral-100);--popover:var(--color-stone-800);--popover-foreground:var(--color-neutral-100);--warning:var(--color-amber-950);--warning-foreground:var(--color-amber-200);--chart-1:#ff6b33;--chart-2:#00b3a4;--chart-3:#2196a8;--chart-4:#ffc733;--chart-5:#ffad33;--chart-negative:#ff6b33;--chart-positive:#00b3a4;--chart-fill:#3382ff40;--chart-fill-2:#5096ff33;--chart-stroke-2:#5da3ff;--sidebar:var(--color-stone-800);--sidebar-foreground:var(--color-neutral-300);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-stone-700);--sidebar-ring:var(--ring);--backdrop:#000c;--theme-background:#0c0a09}[data-theme=metropolis]{--background:var(--color-white);--background-emphasis:var(--color-neutral-900);--foreground:var(--color-neutral-950);--foreground-alt:var(--color-neutral-700);--foreground-subtle:var(--color-neutral-600);--primary:var(--color-purple-600);--primary-foreground:var(--color-neutral-50);--primary-hover:var(--color-purple-700);--secondary:var(--color-neutral-100);--secondary-foreground:var(--color-neutral-900);--secondary-hover:var(--color-neutral-50);--muted:var(--color-neutral-100);--muted-foreground:var(--color-neutral-500);--accent:var(--color-purple-50);--accent-foreground:var(--color-purple-600);--destructive:var(--color-red-600);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-100);--destructive-soft-foreground:var(--color-red-800);--ghost:#fff0;--ghost-foreground:var(--color-neutral-700);--ghost-hover:#0000000d;--positive:var(--color-green-100);--positive-foreground:var(--color-green-900);--surface:var(--color-neutral-50);--surface-emphasis:var(--color-neutral-300);--surface-raised:var(--color-neutral-200);--border:var(--color-neutral-200);--border-light:var(--color-neutral-100);--border-lighter:var(--color-neutral-50);--border-strong:var(--color-neutral-400);--input:var(--color-neutral-50);--input-foreground:var(--color-neutral-950);--ring:var(--color-neutral-300);--ring-error:var(--color-red-300);--card:var(--color-white);--card-foreground:var(--color-neutral-950);--popover:var(--color-white);--popover-foreground:var(--color-neutral-950);--warning:var(--color-yellow-100);--warning-foreground:var(--color-yellow-900);--chart-1:#f54a00;--chart-2:#009689;--chart-3:#104e64;--chart-4:#ffb900;--chart-5:#fe9a00;--chart-negative:#f54a00;--chart-positive:#009689;--chart-fill:#bfdeffb3;--chart-fill-2:#aaccffb3;--chart-stroke-2:#3f8dff;--sidebar:var(--color-neutral-50);--sidebar-foreground:var(--color-gray-800);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-neutral-200);--sidebar-ring:var(--color-neutral-300);--backdrop:#0009;--theme-background:#f0f3f8}[data-theme=metropolis].dark,[data-theme=metropolis] .dark{--background:var(--color-stone-900);--background-emphasis:var(--color-neutral-100);--foreground:var(--color-neutral-50);--foreground-alt:var(--color-neutral-300);--foreground-subtle:var(--color-neutral-400);--primary:var(--color-purple-500);--primary-foreground:var(--color-white);--primary-hover:var(--color-purple-400);--secondary:var(--color-stone-700);--secondary-foreground:var(--color-neutral-100);--secondary-hover:var(--color-stone-600);--muted:var(--color-stone-800);--muted-foreground:var(--color-neutral-400);--accent:var(--color-purple-900);--accent-foreground:var(--color-purple-300);--destructive:var(--color-red-500);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-950);--destructive-soft-foreground:var(--color-red-200);--ghost:#fff0;--ghost-foreground:var(--color-neutral-300);--ghost-hover:#ffffff14;--positive:var(--color-green-950);--positive-foreground:var(--color-green-200);--surface:var(--color-stone-800);--surface-emphasis:var(--color-stone-600);--surface-raised:var(--color-stone-700);--border:var(--color-stone-600);--border-light:var(--color-stone-700);--border-lighter:var(--color-stone-800);--border-strong:var(--color-stone-500);--input:var(--color-stone-800);--input-foreground:var(--color-neutral-50);--ring:var(--color-neutral-500);--ring-error:var(--color-red-400);--card:var(--color-stone-800);--card-foreground:var(--color-neutral-100);--popover:var(--color-stone-800);--popover-foreground:var(--color-neutral-100);--warning:var(--color-amber-950);--warning-foreground:var(--color-amber-200);--chart-1:#ff6b33;--chart-2:#00b3a4;--chart-3:#2196a8;--chart-4:#ffc733;--chart-5:#ffad33;--chart-negative:#ff6b33;--chart-positive:#00b3a4;--chart-fill:#3382ff40;--chart-fill-2:#5096ff33;--chart-stroke-2:#5da3ff;--sidebar:var(--color-stone-800);--sidebar-foreground:var(--color-neutral-300);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-stone-700);--sidebar-ring:var(--color-neutral-500);--backdrop:#000c;--theme-background:#0c0a09}*{border-color:var(--border)}body{background-color:var(--background);color:var(--foreground)}button,[role=button]{cursor:pointer}:focus-visible{outline:2px solid var(--ring);outline-offset:2px}}@layer components;@layer utilities{.relative{position:relative}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3\\.5{margin-top:calc(var(--spacing) * 3.5)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-px{margin-top:1px}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:var(--spacing)}.mb-1\\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-11{height:calc(var(--spacing) * 11)}.min-h-svh{min-height:100svh}.w-full{width:100%}.max-w-sm{max-width:var(--container-sm)}.shrink-0{flex-shrink:0}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-center{justify-content:center}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-border{border-color:var(--color-border)}.border-brand{border-color:var(--color-brand)}.border-destructive{border-color:var(--color-destructive)}.bg-\\[color-mix\\(in_oklab\\,var\\(--destructive\\)_8\\%\\,transparent\\)\\]{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-\\[color-mix\\(in_oklab\\,var\\(--destructive\\)_8\\%\\,transparent\\)\\]{background-color:color-mix(in oklab,var(--destructive) 8%,transparent)}}.bg-\\[color-mix\\(in_oklab\\,var\\(--foreground\\)_6\\%\\,transparent\\)\\]{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.bg-\\[color-mix\\(in_oklab\\,var\\(--foreground\\)_6\\%\\,transparent\\)\\]{background-color:color-mix(in oklab,var(--foreground) 6%,transparent)}}.bg-\\[var\\(--input\\)\\]{background-color:var(--input)}.bg-brand{background-color:var(--color-brand)}.bg-card{background-color:var(--color-card)}.bg-destructive{background-color:var(--color-destructive)}.bg-primary{background-color:var(--color-primary)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-px{padding-block:1px}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[0\\.85em\\]{font-size:.85em}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.text-\\[var\\(--card\\)\\]{color:var(--card)}.text-brand{color:var(--color-brand)}.text-brand-foreground{color:var(--color-brand-foreground)}.text-destructive{color:var(--color-destructive)}.text-foreground{color:var(--color-foreground)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.shadow-panel{--tw-shadow:var(--panel-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.backdrop-blur-\\[10px\\]{--tw-backdrop-blur:blur(10px);-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))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}.canopy-backdrop{background:var(--backdrop)}.paused{animation-play-state:paused}.running{animation-play-state:running}@media (hover:hover){.hover\\:bg-\\[var\\(--primary-hover\\)\\]:hover{background-color:var(--primary-hover)}.hover\\:text-foreground:hover{color:var(--color-foreground)}}.focus-visible\\:border-brand:focus-visible{border-color:var(--color-brand)}.focus-visible\\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-offset-\\[3px\\]:focus-visible{outline-offset:3px}.focus-visible\\:outline-brand:focus-visible{outline-color:var(--color-brand)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--color-destructive)}}@property --tw-animation-delay{syntax:\"*\";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:\"*\";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:\"*\";inherits:false}@property --tw-animation-fill-mode{syntax:\"*\";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:\"*\";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:\"*\";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:\"*\";inherits:false;initial-value:0}@media (prefers-reduced-motion:reduce){:root{--duration-instant:0s;--duration-fast:0s;--duration-base:0s;--duration-slow:0s;--duration-slower:0s;--default-transition-duration:0s}[data-vaul-drawer],[data-vaul-overlay]{transition-duration:0s!important;animation-duration:0s!important}}.dark{--input:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--input:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}.dark{--surface:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--surface:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}.dark{--muted:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--muted:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}:root:not(.dark){--background:var(--color-neutral-50)}[data-slot=dialog-content],[data-slot=alert-dialog-content],[data-slot=sheet-content],[data-slot=drawer-content]{background-color:var(--card)}[data-slot=table-body] tr:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){[data-slot=table-body] tr:hover{background-color:color-mix(in oklab, var(--accent) 45%, transparent)}}:root{--brand:#2f6b4f;--brand-foreground:#f4faf6;--foreground:#14201a;--muted-foreground:#4a5c52;--border:#d5ddd7;--card:#ffffffd1;--input:#ffffffe6;--primary:#14201a;--primary-foreground:#f4f7f5;--primary-hover:var(--primary)}@supports (color:color-mix(in lab, red, red)){:root{--primary-hover:color-mix(in oklab, var(--primary) 72%, var(--brand))}}:root{--destructive:#a23b28;--ring:var(--brand);--panel-shadow:0 18px 40px -28px #14201a73;--backdrop:radial-gradient(900px 480px at 12% -10%, #dfece3, transparent 60%), radial-gradient(700px 420px at 100% 0%, #e7efe4, transparent 55%), linear-gradient(165deg, #e8f0ea, #f7f5f0 55%, #eef2ef)}.dark{--brand:#7cc39d;--brand-foreground:#0d1410;--foreground:#e9f0ec;--muted-foreground:#a2b3aa;--border:#e9f0ec24;--card:#181f1bb8;--input:#e9f0ec0f;--primary:#e9f0ec;--primary-foreground:#101711;--primary-hover:var(--primary)}@supports (color:color-mix(in lab, red, red)){.dark{--primary-hover:color-mix(in oklab, var(--primary) 72%, var(--brand))}}.dark{--destructive:#f0a596;--panel-shadow:0 18px 44px -26px #000000b3;--backdrop:radial-gradient(900px 480px at 12% -10%, #16261d, transparent 60%), radial-gradient(700px 420px at 100% 0%, #16221c, transparent 55%), linear-gradient(165deg, #0e1512, #121a15 55%, #0d130f)}@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-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-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-outline-style{syntax:\"*\";inherits:false;initial-value:solid}</style><script>matchMedia('(prefers-color-scheme:dark)').matches&&document.documentElement.classList.add('dark')<\/script></head><body class=\"canopy-backdrop grid min-h-svh place-items-center p-6 text-foreground\"><main class=\"w-full max-w-sm rounded-2xl border border-border bg-card p-8 shadow-panel backdrop-blur-[10px]\"><div class=\"mb-5 grid size-11 place-items-center rounded-xl bg-brand text-brand-foreground\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-check size-5\" aria-hidden=\"true\"><path d=\"M20 6 9 17l-5-5\"></path></svg></div><p class=\"mb-1 text-xs font-semibold uppercase tracking-wide text-brand\">Canopy CLI</p><h1 class=\"mb-2 text-2xl font-semibold tracking-tight break-words\">You’re signed in</h1><p class=\"mt-2 text-sm leading-relaxed text-muted-foreground\">You can close this tab and return to the terminal — the CLI has your code.</p><p class=\"mt-6 border-t border-border pt-4 text-xs text-muted-foreground\">This tab only finishes the browser step — keep using the terminal for the rest.</p></main></body></html>";
9
- const failedHtml = "<!doctype html><html lang=\"en\"><head><meta charSet=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/><title>Sign-in didn’t finish · Canopy</title><style>/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking: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-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-outline-style:solid;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:\"Helvetica Now for Monks\", ui-sans-serif, system-ui, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;--color-red-100:#ffebf0;--color-red-200:#ffd1dd;--color-red-300:#ffa8be;--color-red-400:#ff7a9c;--color-red-500:#ff527d;--color-red-600:#ff245b;--color-red-800:#a30029;--color-red-950:#610018;--color-amber-200:#fde68a;--color-amber-950:#451a03;--color-yellow-100:#fff7db;--color-yellow-900:#7a6000;--color-green-100:#e3fcf1;--color-green-200:#b8fadd;--color-green-900:#067445;--color-green-950:#065533;--color-purple-50:#faf6fd;--color-purple-300:#d6b6f1;--color-purple-400:#c598ec;--color-purple-500:#ac6de3;--color-purple-600:#8c3fd2;--color-purple-700:#7d26c9;--color-purple-900:#501881;--color-gray-800:#5d5d60;--color-neutral-50:#f5f5f4;--color-neutral-100:#e9e8e7;--color-neutral-200:#d6d4d2;--color-neutral-300:#c0beb9;--color-neutral-400:#adaaa4;--color-neutral-500:#97938c;--color-neutral-600:#837f77;--color-neutral-700:#6c6962;--color-neutral-900:#484641;--color-neutral-950:#3e3c38;--color-stone-500:#78716c;--color-stone-600:#57534e;--color-stone-700:#44403c;--color-stone-800:#292524;--color-stone-900:#1c1917;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:12px;--text-xs--line-height:16px;--text-sm:14px;--text-sm--line-height:20px;--text-2xl:24px;--text-2xl--line-height:32px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.01em;--tracking-wide:.015em;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-md:6px;--radius-lg:8px;--radius-xl:12px;--radius-2xl:16px;--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);--color-foreground:var(--foreground);--color-primary:var(--primary);--color-primary-foreground:var(--primary-foreground);--color-muted-foreground:var(--muted-foreground);--color-destructive:var(--destructive);--color-border:var(--border);--color-card:var(--card);--color-brand:var(--brand);--color-brand-foreground:var(--brand-foreground)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root,[data-theme=monks-flow]{--background:var(--color-white);--background-emphasis:var(--color-neutral-900);--foreground:var(--color-neutral-950);--foreground-alt:var(--color-neutral-700);--foreground-subtle:var(--color-neutral-600);--primary:var(--color-neutral-900);--primary-foreground:var(--color-neutral-50);--primary-hover:var(--color-neutral-950);--secondary:#f5f3f0;--secondary-foreground:var(--color-neutral-900);--secondary-hover:#e7e2dc;--muted:var(--color-neutral-100);--muted-foreground:var(--color-neutral-500);--accent:#e7e2dc;--accent-foreground:var(--color-neutral-900);--destructive:#e11d48;--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-100);--destructive-soft-foreground:var(--color-red-800);--ghost:#fff0;--ghost-foreground:var(--color-neutral-700);--ghost-hover:#0000000d;--positive:var(--color-green-100);--positive-foreground:var(--color-green-900);--surface:var(--color-neutral-50);--surface-emphasis:var(--color-neutral-300);--surface-raised:var(--color-neutral-200);--border:var(--color-neutral-200);--border-light:var(--color-neutral-100);--border-lighter:var(--color-neutral-50);--border-strong:var(--color-neutral-400);--input:var(--color-neutral-50);--input-foreground:var(--color-neutral-950);--ring:var(--color-black);--ring-error:var(--color-red-300);--card:var(--color-white);--card-foreground:var(--color-neutral-950);--popover:var(--color-white);--popover-foreground:var(--color-neutral-950);--warning:var(--color-yellow-100);--warning-foreground:var(--color-yellow-900);--chart-1:#f54a00;--chart-2:#009689;--chart-3:#104e64;--chart-4:#ffb900;--chart-5:#fe9a00;--chart-negative:#f54a00;--chart-positive:#009689;--chart-fill:#bfdeffb3;--chart-fill-2:#aaccffb3;--chart-stroke-2:#3f8dff;--sidebar:var(--color-neutral-50);--sidebar-foreground:var(--color-gray-800);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-neutral-200);--sidebar-ring:var(--ring);--backdrop:#0009;--theme-background:#f5f4f2}:root.dark:not([data-theme]),[data-theme=monks-flow].dark,[data-theme=monks-flow] .dark{--background:var(--color-stone-900);--background-emphasis:var(--color-neutral-100);--foreground:var(--color-neutral-50);--foreground-alt:var(--color-neutral-300);--foreground-subtle:var(--color-neutral-400);--primary:var(--color-neutral-50);--primary-foreground:var(--color-black);--primary-hover:var(--color-neutral-100);--secondary:var(--color-stone-700);--secondary-foreground:var(--color-neutral-100);--secondary-hover:var(--color-stone-600);--muted:var(--color-stone-800);--muted-foreground:var(--color-neutral-500);--accent:var(--color-neutral-900);--accent-foreground:var(--color-neutral-300);--destructive:var(--color-red-500);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-950);--destructive-soft-foreground:var(--color-red-200);--ghost:#fff0;--ghost-foreground:var(--color-neutral-300);--ghost-hover:#ffffff14;--positive:var(--color-green-950);--positive-foreground:var(--color-green-200);--surface:var(--color-stone-800);--surface-emphasis:var(--color-stone-600);--surface-raised:var(--color-stone-700);--border:var(--color-stone-600);--border-light:var(--color-stone-700);--border-lighter:var(--color-stone-800);--border-strong:var(--color-stone-500);--input:var(--color-stone-800);--input-foreground:var(--color-neutral-50);--ring:var(--color-white);--ring-error:var(--color-red-400);--card:var(--color-stone-800);--card-foreground:var(--color-neutral-100);--popover:var(--color-stone-800);--popover-foreground:var(--color-neutral-100);--warning:var(--color-amber-950);--warning-foreground:var(--color-amber-200);--chart-1:#ff6b33;--chart-2:#00b3a4;--chart-3:#2196a8;--chart-4:#ffc733;--chart-5:#ffad33;--chart-negative:#ff6b33;--chart-positive:#00b3a4;--chart-fill:#3382ff40;--chart-fill-2:#5096ff33;--chart-stroke-2:#5da3ff;--sidebar:var(--color-stone-800);--sidebar-foreground:var(--color-neutral-300);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-stone-700);--sidebar-ring:var(--ring);--backdrop:#000c;--theme-background:#0c0a09}[data-theme=metropolis]{--background:var(--color-white);--background-emphasis:var(--color-neutral-900);--foreground:var(--color-neutral-950);--foreground-alt:var(--color-neutral-700);--foreground-subtle:var(--color-neutral-600);--primary:var(--color-purple-600);--primary-foreground:var(--color-neutral-50);--primary-hover:var(--color-purple-700);--secondary:var(--color-neutral-100);--secondary-foreground:var(--color-neutral-900);--secondary-hover:var(--color-neutral-50);--muted:var(--color-neutral-100);--muted-foreground:var(--color-neutral-500);--accent:var(--color-purple-50);--accent-foreground:var(--color-purple-600);--destructive:var(--color-red-600);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-100);--destructive-soft-foreground:var(--color-red-800);--ghost:#fff0;--ghost-foreground:var(--color-neutral-700);--ghost-hover:#0000000d;--positive:var(--color-green-100);--positive-foreground:var(--color-green-900);--surface:var(--color-neutral-50);--surface-emphasis:var(--color-neutral-300);--surface-raised:var(--color-neutral-200);--border:var(--color-neutral-200);--border-light:var(--color-neutral-100);--border-lighter:var(--color-neutral-50);--border-strong:var(--color-neutral-400);--input:var(--color-neutral-50);--input-foreground:var(--color-neutral-950);--ring:var(--color-neutral-300);--ring-error:var(--color-red-300);--card:var(--color-white);--card-foreground:var(--color-neutral-950);--popover:var(--color-white);--popover-foreground:var(--color-neutral-950);--warning:var(--color-yellow-100);--warning-foreground:var(--color-yellow-900);--chart-1:#f54a00;--chart-2:#009689;--chart-3:#104e64;--chart-4:#ffb900;--chart-5:#fe9a00;--chart-negative:#f54a00;--chart-positive:#009689;--chart-fill:#bfdeffb3;--chart-fill-2:#aaccffb3;--chart-stroke-2:#3f8dff;--sidebar:var(--color-neutral-50);--sidebar-foreground:var(--color-gray-800);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-neutral-200);--sidebar-ring:var(--color-neutral-300);--backdrop:#0009;--theme-background:#f0f3f8}[data-theme=metropolis].dark,[data-theme=metropolis] .dark{--background:var(--color-stone-900);--background-emphasis:var(--color-neutral-100);--foreground:var(--color-neutral-50);--foreground-alt:var(--color-neutral-300);--foreground-subtle:var(--color-neutral-400);--primary:var(--color-purple-500);--primary-foreground:var(--color-white);--primary-hover:var(--color-purple-400);--secondary:var(--color-stone-700);--secondary-foreground:var(--color-neutral-100);--secondary-hover:var(--color-stone-600);--muted:var(--color-stone-800);--muted-foreground:var(--color-neutral-400);--accent:var(--color-purple-900);--accent-foreground:var(--color-purple-300);--destructive:var(--color-red-500);--destructive-foreground:var(--color-white);--destructive-soft:var(--color-red-950);--destructive-soft-foreground:var(--color-red-200);--ghost:#fff0;--ghost-foreground:var(--color-neutral-300);--ghost-hover:#ffffff14;--positive:var(--color-green-950);--positive-foreground:var(--color-green-200);--surface:var(--color-stone-800);--surface-emphasis:var(--color-stone-600);--surface-raised:var(--color-stone-700);--border:var(--color-stone-600);--border-light:var(--color-stone-700);--border-lighter:var(--color-stone-800);--border-strong:var(--color-stone-500);--input:var(--color-stone-800);--input-foreground:var(--color-neutral-50);--ring:var(--color-neutral-500);--ring-error:var(--color-red-400);--card:var(--color-stone-800);--card-foreground:var(--color-neutral-100);--popover:var(--color-stone-800);--popover-foreground:var(--color-neutral-100);--warning:var(--color-amber-950);--warning-foreground:var(--color-amber-200);--chart-1:#ff6b33;--chart-2:#00b3a4;--chart-3:#2196a8;--chart-4:#ffc733;--chart-5:#ffad33;--chart-negative:#ff6b33;--chart-positive:#00b3a4;--chart-fill:#3382ff40;--chart-fill-2:#5096ff33;--chart-stroke-2:#5da3ff;--sidebar:var(--color-stone-800);--sidebar-foreground:var(--color-neutral-300);--sidebar-primary:var(--primary);--sidebar-primary-foreground:var(--primary-foreground);--sidebar-accent:var(--accent);--sidebar-accent-foreground:var(--accent-foreground);--sidebar-border:var(--color-stone-700);--sidebar-ring:var(--color-neutral-500);--backdrop:#000c;--theme-background:#0c0a09}*{border-color:var(--border)}body{background-color:var(--background);color:var(--foreground)}button,[role=button]{cursor:pointer}:focus-visible{outline:2px solid var(--ring);outline-offset:2px}}@layer components;@layer utilities{.relative{position:relative}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3\\.5{margin-top:calc(var(--spacing) * 3.5)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-px{margin-top:1px}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:var(--spacing)}.mb-1\\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-11{height:calc(var(--spacing) * 11)}.min-h-svh{min-height:100svh}.w-full{width:100%}.max-w-sm{max-width:var(--container-sm)}.shrink-0{flex-shrink:0}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-center{justify-content:center}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-border{border-color:var(--color-border)}.border-brand{border-color:var(--color-brand)}.border-destructive{border-color:var(--color-destructive)}.bg-\\[color-mix\\(in_oklab\\,var\\(--destructive\\)_8\\%\\,transparent\\)\\]{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-\\[color-mix\\(in_oklab\\,var\\(--destructive\\)_8\\%\\,transparent\\)\\]{background-color:color-mix(in oklab,var(--destructive) 8%,transparent)}}.bg-\\[color-mix\\(in_oklab\\,var\\(--foreground\\)_6\\%\\,transparent\\)\\]{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.bg-\\[color-mix\\(in_oklab\\,var\\(--foreground\\)_6\\%\\,transparent\\)\\]{background-color:color-mix(in oklab,var(--foreground) 6%,transparent)}}.bg-\\[var\\(--input\\)\\]{background-color:var(--input)}.bg-brand{background-color:var(--color-brand)}.bg-card{background-color:var(--color-card)}.bg-destructive{background-color:var(--color-destructive)}.bg-primary{background-color:var(--color-primary)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-px{padding-block:1px}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[0\\.85em\\]{font-size:.85em}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.text-\\[var\\(--card\\)\\]{color:var(--card)}.text-brand{color:var(--color-brand)}.text-brand-foreground{color:var(--color-brand-foreground)}.text-destructive{color:var(--color-destructive)}.text-foreground{color:var(--color-foreground)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.shadow-panel{--tw-shadow:var(--panel-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.backdrop-blur-\\[10px\\]{--tw-backdrop-blur:blur(10px);-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))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}.canopy-backdrop{background:var(--backdrop)}.paused{animation-play-state:paused}.running{animation-play-state:running}@media (hover:hover){.hover\\:bg-\\[var\\(--primary-hover\\)\\]:hover{background-color:var(--primary-hover)}.hover\\:text-foreground:hover{color:var(--color-foreground)}}.focus-visible\\:border-brand:focus-visible{border-color:var(--color-brand)}.focus-visible\\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\\:outline-offset-1:focus-visible{outline-offset:1px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-offset-\\[3px\\]:focus-visible{outline-offset:3px}.focus-visible\\:outline-brand:focus-visible{outline-color:var(--color-brand)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--color-destructive)}}@property --tw-animation-delay{syntax:\"*\";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:\"*\";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:\"*\";inherits:false}@property --tw-animation-fill-mode{syntax:\"*\";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:\"*\";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:\"*\";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:\"*\";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:\"*\";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:\"*\";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:\"*\";inherits:false;initial-value:0}@media (prefers-reduced-motion:reduce){:root{--duration-instant:0s;--duration-fast:0s;--duration-base:0s;--duration-slow:0s;--duration-slower:0s;--default-transition-duration:0s}[data-vaul-drawer],[data-vaul-overlay]{transition-duration:0s!important;animation-duration:0s!important}}.dark{--input:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--input:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}.dark{--surface:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--surface:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}.dark{--muted:#35312f}@supports (color:color-mix(in lab, red, red)){.dark{--muted:color-mix(in oklab, var(--color-stone-800) 55%, var(--color-stone-700))}}:root:not(.dark){--background:var(--color-neutral-50)}[data-slot=dialog-content],[data-slot=alert-dialog-content],[data-slot=sheet-content],[data-slot=drawer-content]{background-color:var(--card)}[data-slot=table-body] tr:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){[data-slot=table-body] tr:hover{background-color:color-mix(in oklab, var(--accent) 45%, transparent)}}:root{--brand:#2f6b4f;--brand-foreground:#f4faf6;--foreground:#14201a;--muted-foreground:#4a5c52;--border:#d5ddd7;--card:#ffffffd1;--input:#ffffffe6;--primary:#14201a;--primary-foreground:#f4f7f5;--primary-hover:var(--primary)}@supports (color:color-mix(in lab, red, red)){:root{--primary-hover:color-mix(in oklab, var(--primary) 72%, var(--brand))}}:root{--destructive:#a23b28;--ring:var(--brand);--panel-shadow:0 18px 40px -28px #14201a73;--backdrop:radial-gradient(900px 480px at 12% -10%, #dfece3, transparent 60%), radial-gradient(700px 420px at 100% 0%, #e7efe4, transparent 55%), linear-gradient(165deg, #e8f0ea, #f7f5f0 55%, #eef2ef)}.dark{--brand:#7cc39d;--brand-foreground:#0d1410;--foreground:#e9f0ec;--muted-foreground:#a2b3aa;--border:#e9f0ec24;--card:#181f1bb8;--input:#e9f0ec0f;--primary:#e9f0ec;--primary-foreground:#101711;--primary-hover:var(--primary)}@supports (color:color-mix(in lab, red, red)){.dark{--primary-hover:color-mix(in oklab, var(--primary) 72%, var(--brand))}}.dark{--destructive:#f0a596;--panel-shadow:0 18px 44px -26px #000000b3;--backdrop:radial-gradient(900px 480px at 12% -10%, #16261d, transparent 60%), radial-gradient(700px 420px at 100% 0%, #16221c, transparent 55%), linear-gradient(165deg, #0e1512, #121a15 55%, #0d130f)}@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-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-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-outline-style{syntax:\"*\";inherits:false;initial-value:solid}</style><script>matchMedia('(prefers-color-scheme:dark)').matches&&document.documentElement.classList.add('dark')<\/script></head><body class=\"canopy-backdrop grid min-h-svh place-items-center p-6 text-foreground\"><main class=\"w-full max-w-sm rounded-2xl border border-border bg-card p-8 shadow-panel backdrop-blur-[10px]\"><div class=\"mb-5 grid size-11 place-items-center rounded-xl bg-destructive text-[var(--card)]\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-alert size-5\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\"></line><line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\"></line></svg></div><p class=\"mb-1 text-xs font-semibold uppercase tracking-wide text-brand\">Canopy CLI</p><h1 class=\"mb-2 text-2xl font-semibold tracking-tight break-words\">Sign-in didn’t finish</h1><p class=\"mt-2 text-sm leading-relaxed text-muted-foreground\">Return to the terminal and run canopy login again. Reloading this page won’t help.</p><p class=\"mt-6 border-t border-border pt-4 text-xs text-muted-foreground\">If the terminal still says it’s waiting, cancel with <kbd class=\"rounded border border-border bg-[var(--input)] px-1 py-px text-[0.85em] font-normal\">Ctrl</kbd>+<kbd class=\"rounded border border-border bg-[var(--input)] px-1 py-px text-[0.85em] font-normal\">C</kbd> and try again.</p></main></body></html>";
10
- //#endregion
11
- //#region src/login-page.ts
12
- /**
13
- * Branded HTML for the local OneLogin PKCE callback (127.0.0.1:8976). The page
14
- * lives in @mediamonks/canopy-pages next to the gateway's sign-in and error
15
- * walls so all seven look like one another, and is pre-rendered there at build
16
- * time: it takes no data, and the CLI has no business shipping React and an
17
- * icon set to print two fixed documents.
18
- */
19
- function loginCallbackPage(ok) {
20
- return ok ? okHtml : failedHtml;
21
- }
22
- //#endregion
23
- //#region src/login.ts
24
- /**
25
- * canopy login | whoami | logout — browser PKCE flow against OneLogin (public
26
- * client), then trade the ID token for platform CLI tokens via POST
27
- * /control/v1/auth/cli-token on every baked site (docs/10-cli-sites.md D17).
28
- */
29
- const CALLBACK_PORT = 8976;
30
- const REDIRECT_URI = `http://127.0.0.1:${CALLBACK_PORT}/callback`;
31
- const LOGIN_TIMEOUT_MS = 300 * 1e3;
32
- const base64url = (buf) => buf.toString("base64url");
33
- const whoamiCommand = defineCommand({
34
- meta: {
35
- name: "whoami",
36
- description: "Show the current Canopy login"
37
- },
38
- run: reportErrors("whoami", async () => {
39
- const config = siteConfig();
40
- if (!config.token) throw new Error("Not logged in — run `canopy login`.");
41
- console.log(config.email ?? "<unknown email>");
42
- if (config.cloud) console.log(`Cloud: ${config.cloud}`);
43
- console.log(`API: ${config.apiUrl}`);
44
- if (config.tokenExpiresAt !== void 0) {
45
- const expired = Date.parse(config.tokenExpiresAt) < Date.now();
46
- console.log(expired ? `Token EXPIRED ${config.tokenExpiresAt} — run \`canopy login\` again.` : `Token expires ${config.tokenExpiresAt}.`);
47
- }
48
- })
49
- });
50
- const logoutCommand = defineCommand({
51
- meta: {
52
- name: "logout",
53
- description: "Sign out: forget all local CLI tokens"
54
- },
55
- run: reportErrors("logout", async () => {
56
- const file = readConfigFile();
57
- if (!Object.values(file.profiles ?? {}).some((p) => p?.token)) {
58
- console.log("Not logged in.");
59
- return;
60
- }
61
- clearAllProfileTokens();
62
- console.log("Logged out — all site tokens removed from ~/.canopy/config.json.");
63
- })
64
- });
65
- /** Wait for OneLogin to redirect back to the local loopback server. */
66
- function waitForCallback(expectedState) {
67
- return new Promise((resolve, reject) => {
68
- const server = createServer((req, res) => {
69
- const url = new URL(req.url ?? "/", REDIRECT_URI);
70
- if (url.pathname !== "/callback") {
71
- res.writeHead(404).end();
72
- return;
73
- }
74
- const code = url.searchParams.get("code");
75
- const state = url.searchParams.get("state");
76
- const ok = Boolean(code) && state === expectedState;
77
- res.writeHead(ok ? 200 : 400, {
78
- "content-type": "text/html; charset=utf-8",
79
- "cache-control": "no-store"
80
- }).end(loginCallbackPage(ok));
81
- server.close();
82
- clearTimeout(timer);
83
- if (ok) resolve(code);
84
- else reject(new Error(url.searchParams.get("error_description") ?? "Login rejected"));
85
- });
86
- const timer = setTimeout(() => {
87
- server.close();
88
- reject(/* @__PURE__ */ new Error("Timed out waiting for the browser login (5 minutes)."));
89
- }, LOGIN_TIMEOUT_MS);
90
- server.on("error", (err) => reject(err.message.includes("EADDRINUSE") ? /* @__PURE__ */ new Error(`Port ${CALLBACK_PORT} is in use — close the other process and retry.`) : err));
91
- server.listen(CALLBACK_PORT, "127.0.0.1");
92
- });
93
- }
94
- async function pickActiveProfile(json, flag) {
95
- if (flag) {
96
- if (!isProfileId(flag)) throw new Error(`Unknown profile "${flag}". Choose one of: ${listBakedProfiles().map((p) => p.id).join(", ")}.`);
97
- return flag;
98
- }
99
- const env = process.env["CANOPY_PROFILE"]?.trim();
100
- if (env) {
101
- if (!isProfileId(env)) throw new Error(`Unknown CANOPY_PROFILE "${env}".`);
102
- return env;
103
- }
104
- const profiles = listBakedProfiles();
105
- if (!process.stdin.isTTY || json) throw new Error(`Pass --profile <id> (or CANOPY_PROFILE) when not on a TTY. Options: ${profiles.map((p) => p.id).join(", ")}.`);
106
- const choice = await p.select({
107
- message: "Which Canopy site should be your default?",
108
- options: profiles.map((prof) => ({
109
- value: prof.id,
110
- label: prof.label,
111
- hint: prof.cloud
112
- })),
113
- initialValue: "main"
114
- });
115
- if (p.isCancel(choice)) {
116
- p.cancel("Login cancelled.");
117
- process.exit(1);
118
- }
119
- p.note(`Using profile "${choice}". Agents/non-TTY: canopy login --profile ${choice}`, "Active profile");
120
- return choice;
121
- }
122
- async function mintForProfile(id, idToken) {
123
- const baked = getBakedProfile(id);
124
- try {
125
- const cliTokenRes = await fetch(`${baked.apiUrl}/control/v1/auth/cli-token`, {
126
- method: "POST",
127
- headers: { "content-type": "application/json" },
128
- body: JSON.stringify({ id_token: idToken })
129
- });
130
- if (!cliTokenRes.ok) return {
131
- ok: false,
132
- error: `${cliTokenRes.status} ${await cliTokenRes.text()}`
133
- };
134
- const { token, expires_at, user } = await cliTokenRes.json();
135
- upsertProfileAuth(id, {
136
- token,
137
- tokenExpiresAt: expires_at,
138
- email: user.email
139
- });
140
- return {
141
- ok: true,
142
- email: user.email,
143
- expiresAt: expires_at
144
- };
145
- } catch (err) {
146
- return {
147
- ok: false,
148
- error: err instanceof Error ? err.message : String(err)
149
- };
150
- }
151
- }
152
- async function login(json, profileFlag) {
153
- if (!json) p.intro("canopy login");
154
- const active = await pickActiveProfile(json, profileFlag);
155
- const file = readConfigFile();
156
- const { issuer, cliClientId } = {
157
- issuer: process.env["CANOPY_OIDC_ISSUER"] ?? file.issuer ?? "https://s4capital.onelogin.com/oidc/2",
158
- cliClientId: process.env["CANOPY_OIDC_CLIENT_ID"] ?? file.cliClientId ?? "b69755d0-6678-013f-b5ce-09fe44a57aa0180501"
159
- };
160
- if (cliClientId.includes("REPLACE")) throw new Error("The CLI's OneLogin app is not configured yet (set CANOPY_OIDC_CLIENT_ID or packages/cli/src/config.ts).");
161
- writeConfigFile({
162
- ...file,
163
- issuer,
164
- cliClientId,
165
- activeProfile: active
166
- });
167
- const discoveryRes = await fetch(`${issuer}/.well-known/openid-configuration`);
168
- if (!discoveryRes.ok) throw new Error(`OIDC discovery failed: ${discoveryRes.status}`);
169
- const discovery = await discoveryRes.json();
170
- const state = base64url(randomBytes(32));
171
- const codeVerifier = base64url(randomBytes(32));
172
- const authorizeUrl = new URL(discovery.authorization_endpoint);
173
- authorizeUrl.search = new URLSearchParams({
174
- response_type: "code",
175
- client_id: cliClientId,
176
- redirect_uri: REDIRECT_URI,
177
- scope: "openid profile email",
178
- state,
179
- code_challenge: base64url(createHash("sha256").update(codeVerifier).digest()),
180
- code_challenge_method: "S256"
181
- }).toString();
182
- const authorizeHref = authorizeUrl.toString();
183
- openBrowser(authorizeHref);
184
- const spin = json ? void 0 : p.spinner();
185
- if (json) console.log(JSON.stringify({
186
- status: "waiting",
187
- url: authorizeHref
188
- }));
189
- else {
190
- p.log.step("Opening OneLogin in your browser");
191
- p.log.message("If nothing opens, visit:");
192
- console.log(authorizeHref);
193
- spin?.start("Waiting for you to sign in in the browser…");
194
- }
195
- let code;
196
- try {
197
- code = await waitForCallback(state);
198
- } catch (err) {
199
- spin?.error("Sign-in failed.");
200
- throw err;
201
- }
202
- spin?.stop("Signed in with OneLogin.");
203
- const tokenRes = await fetch(discovery.token_endpoint, {
204
- method: "POST",
205
- headers: { "content-type": "application/x-www-form-urlencoded" },
206
- body: new URLSearchParams({
207
- grant_type: "authorization_code",
208
- client_id: cliClientId,
209
- code,
210
- redirect_uri: REDIRECT_URI,
211
- code_verifier: codeVerifier
212
- })
213
- });
214
- if (!tokenRes.ok) throw new Error(`Token exchange failed: ${tokenRes.status} ${await tokenRes.text()}`);
215
- const { id_token: idToken } = await tokenRes.json();
216
- if (!idToken) throw new Error("OneLogin returned no id_token.");
217
- const mintSpin = json ? void 0 : p.spinner();
218
- mintSpin?.start("Minting CLI tokens for each site…");
219
- const results = [];
220
- for (const prof of listBakedProfiles()) {
221
- const result = await mintForProfile(prof.id, idToken);
222
- results.push({
223
- id: prof.id,
224
- ok: result.ok,
225
- detail: result.ok ? `expires ${result.expiresAt}` : result.error
226
- });
227
- }
228
- mintSpin?.stop("Token mint finished.");
229
- if (!results.find((r) => r.id === active)?.ok) {
230
- const summary = results.map((r) => `${r.id} ${r.ok ? "✓" : "✗"}`).join(" ");
231
- throw new Error(`Could not mint a token for active profile "${active}". ${summary}. Re-run \`canopy login\`.`);
232
- }
233
- setActiveProfile(active);
234
- const email = readConfigFile().profiles?.[active]?.email;
235
- const summary = results.map((r) => `${r.id} ${r.ok ? "✓" : `✗ (${r.detail})`}`).join("\n");
236
- if (json) console.log(JSON.stringify({
237
- status: "ok",
238
- email,
239
- activeProfile: active,
240
- profiles: Object.fromEntries(results.map((r) => [r.id, {
241
- ok: r.ok,
242
- detail: r.detail
243
- }]))
244
- }));
245
- else {
246
- p.note(summary, "Sites");
247
- p.outro(`Logged in as ${email ?? "unknown"} — default profile "${active}".`);
248
- for (const r of results.filter((x) => !x.ok)) p.log.warn(`${r.id} failed — re-run \`canopy login\` to retry all sites.`);
249
- }
250
- }
251
- const loginCommand = defineCommand({
252
- meta: {
253
- name: "login",
254
- description: "Sign in to Canopy via OneLogin"
255
- },
256
- args: {
257
- json: {
258
- type: "boolean",
259
- default: false,
260
- description: "Emit machine-readable status to stdout (for agents/CI)"
261
- },
262
- profile: {
263
- type: "string",
264
- description: "Active default profile (main | staging | gcp-pilot); required non-TTY"
265
- }
266
- },
267
- run: reportErrors("login", async ({ args }) => {
268
- const json = args.json;
269
- try {
270
- await login(json, args.profile);
271
- } catch (err) {
272
- if (json) {
273
- console.log(JSON.stringify({
274
- status: "error",
275
- message: err instanceof Error ? err.message : String(err)
276
- }));
277
- process.exitCode = 1;
278
- return;
279
- }
280
- throw err;
281
- }
282
- })
283
- });
284
- //#endregion
285
- export { loginCommand, logoutCommand, whoamiCommand };