@joycostudio/studio 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -4
- package/dist/{chunk-DEJYGBPJ.js → chunk-OEJWPWYJ.js} +1 -1
- package/dist/chunk-OEJWPWYJ.js.map +1 -0
- package/dist/{chunk-ZH3NEN4V.js → chunk-ZPKMVZ67.js} +103 -41
- package/dist/chunk-ZPKMVZ67.js.map +1 -0
- package/dist/cli.js +30 -11
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +33 -5
- package/dist/client.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/next.d.ts +3 -1
- package/dist/next.js +2 -2
- package/dist/{protocol-DjrMADPm.d.ts → protocol-BviGBdSG.d.ts} +7 -5
- package/dist/react.d.ts +46 -5
- package/dist/react.js +461 -362
- package/dist/react.js.map +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui.d.ts +43 -0
- package/dist/ui.js +80 -0
- package/dist/ui.js.map +1 -0
- package/package.json +13 -4
- package/dist/chunk-DEJYGBPJ.js.map +0 -1
- package/dist/chunk-ZH3NEN4V.js.map +0 -1
package/dist/runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as Op, c as Operations, R as Result,
|
|
1
|
+
import { O as Op, c as Operations, R as Result, k as ToolState, f as StudioTool } from './protocol-BviGBdSG.js';
|
|
2
2
|
import '@joycostudio/xyz/debug';
|
|
3
3
|
|
|
4
4
|
type RuntimeListener = (state: ToolState, origin: unknown) => void;
|
package/dist/runtime.js
CHANGED
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--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-border-style:solid;--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-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-ease:initial;--tw-content:"";--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{--color-sky-400:oklch(74.6% .16 232.661);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-xs:.125rem;--radius-lg:calc(var(--radius) + 2px);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--studio-font);--default-mono-font-family:var(--studio-font);--color-border:var(--border);--color-sidebar:var(--sidebar)}}@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}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklab, var(--ring) 50%, transparent)}}body{background-color:var(--background);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--foreground)}}@layer components{.studio-surface{border-radius:calc(var(--radius) - 2px);background:var(--card);padding:6px}.studio-toolbar{pointer-events:auto;flex-wrap:wrap;align-items:center;gap:4px;display:flex}.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]{border-radius:calc(var(--radius) - 2px);min-height:28px;color:var(--muted-foreground);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:1px solid #0000;align-items:center;gap:6px;padding:4px 8px;font-size:11px;display:inline-flex}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):hover{color:var(--foreground);background:var(--field-hover)}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):is(:active,[aria-pressed=true]){color:var(--foreground);background:var(--field-active)}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):focus-visible{outline:2px solid var(--ring);outline-offset:2px}.studio-canvas-toolbar{z-index:20;min-width:0;color:var(--muted-foreground);pointer-events:none;flex-shrink:0;position:relative}.studio-canvas-actions{opacity:1;transition:opacity .2s ease-out,translate .2s ease-out;translate:0}.studio-canvas-toolbar[data-ghost]{position:absolute;inset:4px 4px auto}.studio-canvas-toolbar[data-ghost]:before{content:"";pointer-events:auto;height:24px;position:absolute;inset:-4px 0 auto}.studio-canvas-toolbar[data-ghost] .studio-canvas-actions{-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);opacity:0;transition-delay:3s;translate:0 calc(-100% - 8px)}.studio-canvas-toolbar[data-ghost]:is(:hover,:has(:focus-visible,[aria-expanded=true],[data-state=open])) .studio-canvas-actions{opacity:1;transition-delay:0s;translate:0}@media (hover:none){.studio-canvas-toolbar[data-ghost] .studio-canvas-actions{opacity:1;translate:0}}.studio-canvas-toolbar[data-expanded]{height:80px;position:absolute;inset:0 0 auto}.studio-canvas-toolbar[data-expanded] .studio-canvas-actions{pointer-events:none;background:0 0;height:100%;padding:0}.studio-canvas-toolbar[data-expanded] .studio-canvas-actions>:not(.studio-canvas-toggle){display:none}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle{width:min(280px,100%);height:100%;padding-top:max(12px, env(safe-area-inset-top));pointer-events:auto;justify-content:center;align-items:flex-start;margin-inline:auto;display:flex}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{border-color:var(--sidebar-border);border-radius:var(--radius);min-height:30px;color:var(--foreground);background:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{background:color-mix(in srgb, var(--sidebar) 85%, transparent)}}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);font-size:inherit;opacity:0;transition:opacity .2s ease-out 3s,translate .2s ease-out 3s;translate:0 -8px;box-shadow:0 4px 12px #0006}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button:hover{background:var(--field-hover)}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle:hover>button,.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button:focus-visible{opacity:1;transition-delay:0s;translate:0}@media (hover:none){.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{opacity:1;translate:0}}@media (prefers-reduced-motion:reduce){.studio-canvas-actions,.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{transition-duration:0s}}.studio-preview-canvas{border:1px solid var(--sidebar-border);border-radius:calc(var(--radius) + 2px);background:var(--sidebar);flex-direction:column;gap:4px;min-width:0;min-height:0;padding:4px;display:flex;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.studio-preview-canvas{background:color-mix(in srgb, var(--sidebar) 85%, transparent)}}.studio-preview-canvas{font:12px/1.5 var(--studio-font);box-shadow:0 12px 24px #0006}.studio-preview-source{align-items:center;min-width:0;margin-right:auto;display:flex}.studio-preview-title{padding-inline:8px}.studio-preview-canvas>iframe{border-radius:calc(var(--radius) - 2px);background:var(--background);border:0;flex:1;width:100%;min-height:0}.studio-preview-canvas[data-expanded]{z-index:30;background:var(--background);border:0;border-radius:0;padding:0;position:fixed;inset:0}.studio-preview-canvas[data-expanded]>iframe{border-radius:0}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.inset-y-2{inset-block:calc(var(--spacing) * 2)}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:0}.right-1{right:var(--spacing)}.right-2{right:calc(var(--spacing) * 2)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:0}.left-0{left:0}.left-1{left:var(--spacing)}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.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}}.mt-1{margin-top:var(--spacing)}.mt-auto{margin-top:auto}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.aspect-square{aspect-ratio:1}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.h-3\.5{height:calc(var(--spacing) * 3.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-16{height:calc(var(--spacing) * 16)}.h-auto{height:auto}.h-full{height:100%}.h-svh{height:100svh}.max-h-\(--available-height\){max-height:var(--available-height)}.max-h-\[300px\]{max-height:300px}.min-h-0{min-height:0}.min-h-7{min-height:calc(var(--spacing) * 7)}.min-h-svh{min-height:100svh}.w-\(--sidebar-width\){width:var(--sidebar-width)}.w-\(--studio-inspector-width\){width:var(--studio-inspector-width)}.w-3\/4{width:75%}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-full{max-width:100%}.min-w-\(--anchor-width\){min-width:var(--anchor-width)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.origin-\(--transform-origin\){transform-origin:var(--transform-origin)}.-translate-x-\[calc\(100\%\+0\.25rem\)\]{--tw-translate-x:calc(calc(100% + .25rem) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-\[calc\(100\%\+1rem\)\]{--tw-translate-x:calc(calc(100% + 1rem) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[calc\(100\%\+0\.25rem\)\]{--tw-translate-x:calc(100% + .25rem);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[calc\(100\%\+1rem\)\]{--tw-translate-x:calc(100% + 1rem);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-\[calc\(-50\%-2px\)\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-45{rotate:45deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.scroll-py-1{scroll-padding-block:var(--spacing)}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.place-items-center{place-items:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:var(--spacing)}.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)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-\[2px\]{border-radius:2px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:calc(var(--radius) + 2px)}.rounded-md{border-radius:var(--radius)}.rounded-sm{border-radius:calc(var(--radius) - 2px)}.rounded-xs{border-radius:var(--radius-xs)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-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-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-sidebar-border{border-color:var(--sidebar-border)}.bg-\(--field\){background-color:var(--field)}.bg-background{background-color:var(--background)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-current{background-color:currentColor}.bg-destructive{background-color:var(--destructive)}.bg-foreground{background-color:var(--foreground)}.bg-muted{background-color:var(--muted)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sidebar,.bg-sidebar\/85{background-color:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.bg-sidebar\/85{background-color:color-mix(in oklab, var(--sidebar) 85%, transparent)}}.bg-transparent{background-color:#0000}.bg-warning{background-color:var(--warning)}.fill-foreground{fill:var(--foreground)}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-0{padding-inline:0}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:0}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.ps-3{padding-inline-start:calc(var(--spacing) * 3)}.pe-3{padding-inline-end:calc(var(--spacing) * 3)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pr-0{padding-right:0}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5\.5{padding-left:calc(var(--spacing) * 5.5)}.text-center{text-align:center}.text-left{text-align:left}.font-\(family-name\:--studio-font\),.font-mono{font-family:var(--studio-font)}.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-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.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-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.text-balance{text-wrap:balance}.text-clip\!{text-overflow:clip!important}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--background)}.text-destructive{color:var(--destructive)}.text-faint{color:var(--faint)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-sidebar-foreground{color:var(--sidebar-foreground)}.text-sidebar-primary{color:var(--sidebar-primary)}.text-sky-400{color:var(--color-sky-400)}.text-success{color:var(--success)}.text-warning{color:var(--warning)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_0_1px_var\(--sidebar-border\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-border));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);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-black\/40{--tw-shadow-color:#0006}@supports (color:color-mix(in lab, red, red)){.shadow-black\/40{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-black) 40%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-sidebar-ring{--tw-ring-color:var(--sidebar-ring)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.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-xl{--tw-backdrop-blur:blur(var(--blur-xl));-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-\[color\,box-shadow\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[left\,right\,width\,translate\]{transition-property:left,right,width,translate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[left\,right\,width\]{transition-property:left,right,width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[padding\]{transition-property:padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[translate\,opacity\]{transition-property:translate,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\,height\,padding\]{transition-property:width,height,padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-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-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.paused{animation-play-state:paused}.running{animation-play-state:running}.group-focus-within\/menu-item\:opacity-100:is(:where(.group\/menu-item):focus-within *){opacity:1}@media (hover:hover){.group-hover\/edge\:translate-x-0:is(:where(.group\/edge):hover *){--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\/edge\:opacity-100:is(:where(.group\/edge):hover *),.group-hover\/menu-item\:opacity-100:is(:where(.group\/menu-item):hover *){opacity:1}}.group-has-data-\[sidebar\=menu-action\]\/menu-item\:pr-8:is(:where(.group\/menu-item):has([data-sidebar=menu-action]) *){padding-right:calc(var(--spacing) * 8)}.group-data-\[collapsible\=icon\]\:hidden:is(:where(.group)[data-collapsible=icon] *){display:none}.group-data-\[collapsible\=icon\]\:size-8\!:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--spacing) * 8)!important;height:calc(var(--spacing) * 8)!important}.group-data-\[collapsible\=icon\]\:w-\(--sidebar-width-icon\):is(:where(.group)[data-collapsible=icon] *){width:var(--sidebar-width-icon)}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)))}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\+2px\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)) + 2px)}.group-data-\[collapsible\=icon\]\:overflow-hidden:is(:where(.group)[data-collapsible=icon] *){overflow:hidden}.group-data-\[collapsible\=icon\]\:p-0\!:is(:where(.group)[data-collapsible=icon] *){padding:0!important}.group-data-\[collapsible\=icon\]\:p-2\!:is(:where(.group)[data-collapsible=icon] *){padding:calc(var(--spacing) * 2)!important}.group-data-\[collapsible\=icon\]\:pl-\[calc\(1\.5rem-0\.875rem\*352\/144\/2\)\]:is(:where(.group)[data-collapsible=icon] *){padding-left:.430556rem}.group-data-\[collapsible\=offcanvas\]\:right-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){right:calc(var(--sidebar-width) * -1)}.group-data-\[collapsible\=offcanvas\]\:left-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){left:calc(var(--sidebar-width) * -1)}.group-data-\[collapsible\=offcanvas\]\:w-0:is(:where(.group)[data-collapsible=offcanvas] *){width:0}.group-data-\[side\=left\]\:border-r:is(:where(.group)[data-side=left] *){border-right-style:var(--tw-border-style);border-right-width:1px}.group-data-\[side\=right\]\:rotate-180:is(:where(.group)[data-side=right] *){rotate:180deg}.group-data-\[side\=right\]\:border-l:is(:where(.group)[data-side=right] *){border-left-style:var(--tw-border-style);border-left-width:1px}@media (hover:hover){.peer-hover\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button):hover~*){color:var(--sidebar-accent-foreground)}}.peer-data-\[active\=true\]\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button)[data-active=true]~*){color:var(--sidebar-accent-foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:-inset-2:after{content:var(--tw-content);inset:calc(var(--spacing) * -2)}@media (hover:hover){.hover\:bg-\(--field-hover\):hover{background-color:var(--field-hover)}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--destructive) 90%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:bg-sidebar-accent:hover{background-color:var(--sidebar-accent)}.hover\:bg-sidebar\/95:hover{background-color:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-sidebar\/95:hover{background-color:color-mix(in oklab, var(--sidebar) 95%, transparent)}}.hover\:bg-transparent:hover{background-color:#0000}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-sidebar-accent-foreground:hover{color:var(--sidebar-accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-\[0_0_0_1px_var\(--sidebar-accent\)\]:hover{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-accent));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:translate-x-0:focus{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.focus\:opacity-100:focus{opacity:1}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + 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-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.active\:bg-sidebar-accent:active{background-color:var(--sidebar-accent)}.active\:bg-transparent:active{background-color:#0000}.active\:text-sidebar-accent-foreground:active{color:var(--sidebar-accent-foreground)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-data-\[variant\=inset\]\:bg-sidebar:has([data-variant=inset]){background-color:var(--sidebar)}.has-\[\>svg\]\:px-1\.5:has(>svg){padding-inline:calc(var(--spacing) * 1.5)}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-disabled\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\:opacity-50[aria-disabled=true]{opacity:.5}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.aria-pressed\:bg-primary[aria-pressed=true]{background-color:var(--primary)}.aria-pressed\:text-primary-foreground[aria-pressed=true]{color:var(--primary-foreground)}.data-closed\:animate-out[data-closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-closed\:duration-300[data-closed]{--tw-duration:.3s;transition-duration:.3s}.data-closed\:fade-out-0[data-closed]{--tw-exit-opacity:0}.data-closed\:zoom-out-95[data-closed]{--tw-exit-scale:.95}.data-closed\:slide-out-to-bottom[data-closed]{--tw-exit-translate-y:100%}.data-closed\:slide-out-to-left[data-closed]{--tw-exit-translate-x:-100%}.data-closed\:slide-out-to-right[data-closed]{--tw-exit-translate-x:100%}.data-closed\:slide-out-to-top[data-closed]{--tw-exit-translate-y:-100%}.data-open\:animate-in[data-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-open\:duration-500[data-open]{--tw-duration:.5s;transition-duration:.5s}.data-open\:fade-in-0[data-open]{--tw-enter-opacity:0}.data-open\:zoom-in-95[data-open]{--tw-enter-scale:.95}.data-open\:slide-in-from-bottom[data-open]{--tw-enter-translate-y:100%}.data-open\:slide-in-from-left[data-open]{--tw-enter-translate-x:-100%}.data-open\:slide-in-from-right[data-open]{--tw-enter-translate-x:100%}.data-open\:slide-in-from-top[data-open]{--tw-enter-translate-y:-100%}.data-\[active\=true\]\:bg-sidebar-accent[data-active=true]{background-color:var(--sidebar-accent)}.data-\[active\=true\]\:font-medium[data-active=true]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.data-\[active\=true\]\:text-sidebar-accent-foreground[data-active=true]{color:var(--sidebar-accent-foreground)}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[highlighted\]\:bg-\(--field-hover\)[data-highlighted]{background-color:var(--field-hover)}.data-\[highlighted\]\:text-accent-foreground[data-highlighted]{color:var(--accent-foreground)}.data-\[instant\]\:animate-none[data-instant]{animation:none}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[side\=bottom\]\:top-1[data-side=bottom]{top:var(--spacing)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\[side\=left\]\:top-1\/2\![data-side=left]{top:50%!important}.data-\[side\=left\]\:-right-1[data-side=left]{right:calc(var(--spacing) * -1)}.data-\[side\=left\]\:-translate-y-1\/2[data-side=left]{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\[side\=right\]\:top-1\/2\![data-side=right]{top:50%!important}.data-\[side\=right\]\:-left-1[data-side=right]{left:calc(var(--spacing) * -1)}.data-\[side\=right\]\:-translate-y-1\/2[data-side=right]{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\[side\=top\]\:-bottom-2\.5[data-side=top]{bottom:calc(var(--spacing) * -2.5)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\[state\=open\]\:opacity-100[data-state=open]{opacity:1}@media (hover:hover){.data-\[state\=open\]\:hover\:bg-sidebar-accent[data-state=open]:hover{background-color:var(--sidebar-accent)}.data-\[state\=open\]\:hover\:text-sidebar-accent-foreground[data-state=open]:hover{color:var(--sidebar-accent-foreground)}}@media (prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}@media (min-width:40rem){.sm\:max-w-sm{max-width:var(--container-sm)}}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:opacity-0{opacity:0}.md\:after\:hidden:after{content:var(--tw-content);display:none}}@media (prefers-color-scheme:dark){.dark\:border-input{border-color:var(--input)}.dark\:bg-destructive\/60{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/60{background-color:color-mix(in oklab, var(--destructive) 60%, transparent)}}.dark\:bg-input\/30{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30{background-color:color-mix(in oklab, var(--input) 30%, transparent)}}@media (hover:hover){.dark\:hover\:bg-accent\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-accent\/50:hover{background-color:color-mix(in oklab, var(--accent) 50%, transparent)}}.dark\:hover\:bg-input\/50:hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\:not\(\[class\*\=\'text-\'\]\)\]\:text-muted-foreground svg:not([class*=text-]){color:var(--muted-foreground)}.\[\&\>button\]\:hidden>button{display:none}.\[\&\>span\:first-child\]\:truncate>span:first-child,.\[\&\>span\:last-child\]\:truncate>span:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.\[\&\>svg\]\:size-3>svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}@media (hover:none){.\[\@media\(hover\:none\)\]\:translate-x-0{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.\[\@media\(hover\:none\)\]\:opacity-100{opacity:1}}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/20{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/20{background-color:color-mix(in oklab, var(--background) 20%, transparent)}}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:text-background{color:var(--background)}@media (prefers-color-scheme:dark){[data-slot=tooltip-content] .dark\:\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/10{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){[data-slot=tooltip-content] .dark\:\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/10{background-color:color-mix(in oklab, var(--background) 10%, transparent)}}}}@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}.studio-workspace{color:var(--foreground);background:var(--background);font:12px/1.5 var(--studio-font);cursor:default}.studio-workspace [data-slot=studio-config-file][href]{cursor:pointer;text-underline-offset:3px;text-decoration:none}.studio-workspace [data-slot=studio-config-file][href]:is(:hover,:focus-visible){text-decoration-line:underline}.studio-workspace [data-slot=studio-config-file][href]:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.studio-workspace :is([data-slot=sidebar-header],[data-slot=sidebar-footer]){isolation:isolate;flex-shrink:0;position:relative}.studio-workspace :is([data-slot=sidebar-header],[data-slot=sidebar-footer]):before{content:"";z-index:-1;border-radius:calc(var(--radius-lg) - .25rem);background:var(--card);pointer-events:none;position:absolute;inset:4px}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]{min-height:36px;color:var(--muted-foreground);gap:10px;font-size:13px;line-height:20px}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]>span:first-child{flex-shrink:0;display:flex}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]:is(:hover,:focus-visible,[data-active=true]){color:var(--sidebar-accent-foreground)}.studio-workspace{--studio-inspector-width:20rem;--preview-left:8px;--preview-right:8px;--preview-bottom:8px;position:relative}@media (min-width:768px){.studio-workspace[data-sidebar-panel=shown]{--preview-left:var(--sidebar-width)}.studio-workspace[data-sidebar-panel=shown]:has([data-slot=sidebar][data-state=collapsed]){--preview-left:calc(var(--sidebar-width-icon) + 1rem + 2px)}}@media (min-width:1024px){.studio-workspace:has([data-slot=studio-inspector][aria-hidden=false]){--preview-right:calc(var(--studio-inspector-width) + 1rem)}}@media (max-width:1023px){.studio-workspace:is(:has(>[data-slot=preview-canvas]:not([data-expanded])),[data-preview-layout=custom]):has([data-slot=studio-inspector][aria-hidden=false]){--preview-bottom:40%}.studio-workspace:is(:has(>[data-slot=preview-canvas]:not([data-expanded])),[data-preview-layout=custom]) [data-slot=studio-inspector]{inset:calc(60% + 8px) 8px 8px var(--preview-left);width:auto}}.studio-workspace>[data-slot=preview-canvas]{z-index:0}.studio-workspace>[data-slot=preview-canvas]:not([data-expanded]){inset:8px var(--preview-right) var(--preview-bottom) var(--preview-left);position:absolute}.studio-workspace>iframe[data-slot=studio-preview]{background:var(--background);border:0;width:100%;height:100%;position:absolute;inset:0}.studio-workspace[data-preview-layout=custom]>iframe[data-slot=studio-preview]{inset:0 calc(var(--preview-right) - 8px) calc(var(--preview-bottom) - 8px) calc(var(--preview-left) - 8px);width:calc(100% - var(--preview-left) - var(--preview-right) + 16px);height:calc(100% - var(--preview-bottom) + 8px)}:root{--background:#000;--foreground:#d6d7dc;--card:#ffffff0a;--card-foreground:#d6d7dc;--popover:#18191c;--popover-foreground:#d6d7dc;--primary:#e6e7ea;--primary-foreground:#000;--secondary:#ffffff14;--secondary-foreground:#d6d7dc;--muted:#18191c;--muted-foreground:#8b8c94;--faint:#5d5e66;--accent:#18191c;--accent-foreground:#d6d7dc;--destructive:#f87171;--success:#4ade80;--warning:#facc15;--border:#26272b;--input:#26272b;--ring:#5d5e66;--radius:.5rem;--field:#ffffff0f;--field-hover:#ffffff17;--field-active:#ffffff1f;--knob:#4a4b52;--knob-hover:#5a5b63;--sidebar:#000;--sidebar-foreground:#8b8c94;--sidebar-primary:#e6e7ea;--sidebar-primary-foreground:#000;--sidebar-accent:#ffffff14;--sidebar-accent-foreground:#d6d7dc;--sidebar-border:#26272b;--sidebar-ring:#5d5e66;--studio-font:ui-monospace, SFMono-Regular, Menlo, monospace;color-scheme:dark}[data-slot=studio-controls] :is(.tp-lblv_l,.tp-fldv_t):first-letter{text-transform:uppercase}@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-border-style{syntax:"*";inherits:false;initial-value:solid}@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-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-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--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-border-style:solid;--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-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-ease:initial;--tw-content:"";--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{--color-sky-400:oklch(74.6% .16 232.661);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-xs:.125rem;--radius-lg:calc(var(--radius) + 2px);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--studio-font);--default-mono-font-family:var(--studio-font);--color-border:var(--border);--color-sidebar:var(--sidebar)}}@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}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklab, var(--ring) 50%, transparent)}}body{background-color:var(--background);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--foreground)}}@layer components{.studio-surface{border-radius:calc(var(--radius) - 2px);background:var(--card);padding:6px}.studio-toolbar{pointer-events:auto;flex-wrap:wrap;align-items:center;gap:4px;display:flex}.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]{border-radius:calc(var(--radius) - 2px);min-height:28px;color:var(--muted-foreground);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:1px solid #0000;align-items:center;gap:6px;padding:4px 8px;font-size:11px;display:inline-flex}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):hover{color:var(--foreground);background:var(--field-hover)}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):is(:active,[aria-pressed=true]){color:var(--foreground);background:var(--field-active)}:is(.studio-toolbar>button:not([data-slot=select-trigger]),.studio-toolbar [data-slot=toolbar-action]):focus-visible{outline:2px solid var(--ring);outline-offset:2px}.studio-canvas-toolbar{z-index:20;min-width:0;color:var(--muted-foreground);pointer-events:none;flex-shrink:0;position:relative}.studio-canvas-actions{opacity:1;transition:opacity .2s ease-out,translate .2s ease-out;translate:0}.studio-canvas-toolbar[data-ghost]{position:absolute;inset:4px 4px auto}.studio-canvas-toolbar[data-ghost]:before{content:"";pointer-events:auto;height:24px;position:absolute;inset:-4px 0 auto}.studio-canvas-toolbar[data-ghost] .studio-canvas-actions{-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);opacity:0;transition-delay:3s;translate:0 calc(-100% - 8px)}.studio-canvas-toolbar[data-ghost]:is(:hover,:has(:focus-visible,[aria-expanded=true],[data-state=open])) .studio-canvas-actions{opacity:1;transition-delay:0s;translate:0}@media (hover:none){.studio-canvas-toolbar[data-ghost] .studio-canvas-actions{opacity:1;translate:0}}.studio-canvas-toolbar[data-expanded]{height:80px;position:absolute;inset:0 0 auto}.studio-canvas-toolbar[data-expanded] .studio-canvas-actions{pointer-events:none;background:0 0;height:100%;padding:0}.studio-canvas-toolbar[data-expanded] .studio-canvas-actions>:not(.studio-canvas-toggle){display:none}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle{width:min(280px,100%);height:100%;padding-top:max(12px, env(safe-area-inset-top));pointer-events:auto;justify-content:center;align-items:flex-start;margin-inline:auto;display:flex}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{border-color:var(--sidebar-border);border-radius:var(--radius);min-height:30px;color:var(--foreground);background:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{background:color-mix(in srgb, var(--sidebar) 85%, transparent)}}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);font-size:inherit;opacity:0;transition:opacity .2s ease-out 3s,translate .2s ease-out 3s;translate:0 -8px;box-shadow:0 4px 12px #0006}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button:hover{background:var(--field-hover)}.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle:hover>button,.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button:focus-visible{opacity:1;transition-delay:0s;translate:0}@media (hover:none){.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{opacity:1;translate:0}}@media (prefers-reduced-motion:reduce){.studio-canvas-actions,.studio-canvas-toolbar[data-expanded] .studio-canvas-toggle>button{transition-duration:0s}}.studio-preview-canvas{border:1px solid var(--sidebar-border);border-radius:calc(var(--radius) + 2px);background:var(--sidebar);flex-direction:column;gap:4px;min-width:0;min-height:0;padding:4px;display:flex;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.studio-preview-canvas{background:color-mix(in srgb, var(--sidebar) 85%, transparent)}}.studio-preview-canvas{font:12px/1.5 var(--studio-font);box-shadow:0 12px 24px #0006}.studio-preview-source{align-items:center;min-width:0;margin-right:auto;display:flex}.studio-preview-title{padding-inline:8px}.studio-preview-canvas>iframe{border-radius:calc(var(--radius) - 2px);background:var(--background);border:0;flex:1;width:100%;min-height:0}.studio-preview-canvas[data-expanded]{z-index:30;background:var(--background);border:0;border-radius:0;padding:0;position:fixed;inset:0}.studio-preview-canvas[data-expanded]>iframe{border-radius:0}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.inset-y-2{inset-block:calc(var(--spacing) * 2)}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-0{right:0}.right-1{right:var(--spacing)}.right-2{right:calc(var(--spacing) * 2)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:0}.left-0{left:0}.left-1{left:var(--spacing)}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.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-1{margin-inline:calc(var(--spacing) * -1)}.mt-1{margin-top:var(--spacing)}.mt-auto{margin-top:auto}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.aspect-square{aspect-ratio:1}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.h-3\.5{height:calc(var(--spacing) * 3.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-16{height:calc(var(--spacing) * 16)}.h-auto{height:auto}.h-full{height:100%}.h-svh{height:100svh}.max-h-\(--available-height\){max-height:var(--available-height)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[300px\]{max-height:300px}.min-h-0{min-height:0}.min-h-7{min-height:calc(var(--spacing) * 7)}.min-h-svh{min-height:100svh}.w-\(--sidebar-width\){width:var(--sidebar-width)}.w-\(--studio-inspector-width\){width:var(--studio-inspector-width)}.w-3\/4{width:75%}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-full{max-width:100%}.min-w-\(--anchor-width\){min-width:var(--anchor-width)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.origin-\(--transform-origin\){transform-origin:var(--transform-origin)}.-translate-x-\[calc\(100\%\+0\.25rem\)\]{--tw-translate-x:calc(calc(100% + .25rem) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-\[calc\(100\%\+1rem\)\]{--tw-translate-x:calc(calc(100% + 1rem) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[calc\(100\%\+0\.25rem\)\]{--tw-translate-x:calc(100% + .25rem);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[calc\(100\%\+1rem\)\]{--tw-translate-x:calc(100% + 1rem);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-\[calc\(-50\%-2px\)\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-45{rotate:45deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.scroll-py-1{scroll-padding-block:var(--spacing)}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.place-items-center{place-items:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-\[2px\]{border-radius:2px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:calc(var(--radius) + 2px)}.rounded-md{border-radius:var(--radius)}.rounded-sm{border-radius:calc(var(--radius) - 2px)}.rounded-xs{border-radius:var(--radius-xs)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-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-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-sidebar-border{border-color:var(--sidebar-border)}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.bg-\(--field\){background-color:var(--field)}.bg-background{background-color:var(--background)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-current{background-color:currentColor}.bg-destructive{background-color:var(--destructive)}.bg-foreground{background-color:var(--foreground)}.bg-muted{background-color:var(--muted)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-sidebar,.bg-sidebar\/85{background-color:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.bg-sidebar\/85{background-color:color-mix(in oklab, var(--sidebar) 85%, transparent)}}.bg-transparent{background-color:#0000}.bg-warning{background-color:var(--warning)}.fill-foreground{fill:var(--foreground)}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-0{padding-inline:0}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:0}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.ps-3{padding-inline-start:calc(var(--spacing) * 3)}.pe-3{padding-inline-end:calc(var(--spacing) * 3)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pr-0{padding-right:0}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5\.5{padding-left:calc(var(--spacing) * 5.5)}.text-center{text-align:center}.text-left{text-align:left}.font-\(family-name\:--studio-font\),.font-mono{font-family:var(--studio-font)}.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-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.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-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.text-balance{text-wrap:balance}.text-clip\!{text-overflow:clip!important}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--background)}.text-destructive{color:var(--destructive)}.text-faint{color:var(--faint)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-sidebar-foreground{color:var(--sidebar-foreground)}.text-sidebar-primary{color:var(--sidebar-primary)}.text-sky-400{color:var(--color-sky-400)}.text-success{color:var(--success)}.text-warning{color:var(--warning)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_0_1px_var\(--sidebar-border\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-border));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);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-black\/40{--tw-shadow-color:#0006}@supports (color:color-mix(in lab, red, red)){.shadow-black\/40{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-black) 40%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-sidebar-ring{--tw-ring-color:var(--sidebar-ring)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);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,)}.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-xl{--tw-backdrop-blur:blur(var(--blur-xl));-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-\[color\,box-shadow\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[left\,right\,width\,translate\]{transition-property:left,right,width,translate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[left\,right\,width\]{transition-property:left,right,width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[padding\]{transition-property:padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[translate\,opacity\]{transition-property:translate,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\,height\,padding\]{transition-property:width,height,padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-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-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.paused{animation-play-state:paused}.running{animation-play-state:running}.group-focus-within\/menu-item\:opacity-100:is(:where(.group\/menu-item):focus-within *){opacity:1}@media (hover:hover){.group-hover\/edge\:translate-x-0:is(:where(.group\/edge):hover *){--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\/edge\:opacity-100:is(:where(.group\/edge):hover *),.group-hover\/menu-item\:opacity-100:is(:where(.group\/menu-item):hover *){opacity:1}}.group-has-data-\[sidebar\=menu-action\]\/menu-item\:pr-8:is(:where(.group\/menu-item):has([data-sidebar=menu-action]) *){padding-right:calc(var(--spacing) * 8)}.group-data-\[collapsible\=icon\]\:hidden:is(:where(.group)[data-collapsible=icon] *){display:none}.group-data-\[collapsible\=icon\]\:size-8\!:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--spacing) * 8)!important;height:calc(var(--spacing) * 8)!important}.group-data-\[collapsible\=icon\]\:w-\(--sidebar-width-icon\):is(:where(.group)[data-collapsible=icon] *){width:var(--sidebar-width-icon)}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)))}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)\+\(--spacing\(4\)\)\+2px\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + (calc(var(--spacing) * 4)) + 2px)}.group-data-\[collapsible\=icon\]\:overflow-hidden:is(:where(.group)[data-collapsible=icon] *){overflow:hidden}.group-data-\[collapsible\=icon\]\:p-0\!:is(:where(.group)[data-collapsible=icon] *){padding:0!important}.group-data-\[collapsible\=icon\]\:p-2\!:is(:where(.group)[data-collapsible=icon] *){padding:calc(var(--spacing) * 2)!important}.group-data-\[collapsible\=icon\]\:pl-\[calc\(1\.5rem-0\.875rem\*352\/144\/2\)\]:is(:where(.group)[data-collapsible=icon] *){padding-left:.430556rem}.group-data-\[collapsible\=offcanvas\]\:right-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){right:calc(var(--sidebar-width) * -1)}.group-data-\[collapsible\=offcanvas\]\:left-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){left:calc(var(--sidebar-width) * -1)}.group-data-\[collapsible\=offcanvas\]\:w-0:is(:where(.group)[data-collapsible=offcanvas] *){width:0}.group-data-\[side\=left\]\:border-r:is(:where(.group)[data-side=left] *){border-right-style:var(--tw-border-style);border-right-width:1px}.group-data-\[side\=right\]\:rotate-180:is(:where(.group)[data-side=right] *){rotate:180deg}.group-data-\[side\=right\]\:border-l:is(:where(.group)[data-side=right] *){border-left-style:var(--tw-border-style);border-left-width:1px}@media (hover:hover){.peer-hover\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button):hover~*){color:var(--sidebar-accent-foreground)}}.peer-data-\[active\=true\]\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button)[data-active=true]~*){color:var(--sidebar-accent-foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:-inset-2:after{content:var(--tw-content);inset:calc(var(--spacing) * -2)}@media (hover:hover){.hover\:bg-\(--field-hover\):hover{background-color:var(--field-hover)}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--destructive) 90%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:bg-secondary:hover,.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:bg-sidebar-accent:hover{background-color:var(--sidebar-accent)}.hover\:bg-sidebar\/95:hover{background-color:var(--sidebar)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-sidebar\/95:hover{background-color:color-mix(in oklab, var(--sidebar) 95%, transparent)}}.hover\:bg-transparent:hover{background-color:#0000}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-sidebar-accent-foreground:hover{color:var(--sidebar-accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-\[0_0_0_1px_var\(--sidebar-accent\)\]:hover{--tw-shadow:0 0 0 1px var(--tw-shadow-color,var(--sidebar-accent));box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}.focus\:translate-x-0:focus{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.focus\:opacity-100:focus{opacity:1}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + 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-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-destructive\/20:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.active\:bg-sidebar-accent:active{background-color:var(--sidebar-accent)}.active\:bg-transparent:active{background-color:#0000}.active\:text-sidebar-accent-foreground:active{color:var(--sidebar-accent-foreground)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled,.inert\:opacity-50:is([inert],[inert] *){opacity:.5}.has-data-\[variant\=inset\]\:bg-sidebar:has([data-variant=inset]){background-color:var(--sidebar)}.has-\[\>svg\]\:px-1\.5:has(>svg){padding-inline:calc(var(--spacing) * 1.5)}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-disabled\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\:opacity-50[aria-disabled=true]{opacity:.5}.aria-invalid\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\:ring-destructive\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 20%, transparent)}}.aria-pressed\:bg-primary[aria-pressed=true]{background-color:var(--primary)}.aria-pressed\:text-primary-foreground[aria-pressed=true]{color:var(--primary-foreground)}.data-closed\:animate-out[data-closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-closed\:duration-300[data-closed]{--tw-duration:.3s;transition-duration:.3s}.data-closed\:fade-out-0[data-closed]{--tw-exit-opacity:0}.data-closed\:zoom-out-95[data-closed]{--tw-exit-scale:.95}.data-closed\:slide-out-to-bottom[data-closed]{--tw-exit-translate-y:100%}.data-closed\:slide-out-to-left[data-closed]{--tw-exit-translate-x:-100%}.data-closed\:slide-out-to-right[data-closed]{--tw-exit-translate-x:100%}.data-closed\:slide-out-to-top[data-closed]{--tw-exit-translate-y:-100%}.data-open\:animate-in[data-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-open\:duration-500[data-open]{--tw-duration:.5s;transition-duration:.5s}.data-open\:fade-in-0[data-open]{--tw-enter-opacity:0}.data-open\:zoom-in-95[data-open]{--tw-enter-scale:.95}.data-open\:slide-in-from-bottom[data-open]{--tw-enter-translate-y:100%}.data-open\:slide-in-from-left[data-open]{--tw-enter-translate-x:-100%}.data-open\:slide-in-from-right[data-open]{--tw-enter-translate-x:100%}.data-open\:slide-in-from-top[data-open]{--tw-enter-translate-y:-100%}.data-\[active\=true\]\:bg-sidebar-accent[data-active=true]{background-color:var(--sidebar-accent)}.data-\[active\=true\]\:font-medium[data-active=true]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.data-\[active\=true\]\:text-sidebar-accent-foreground[data-active=true]{color:var(--sidebar-accent-foreground)}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[highlighted\]\:bg-\(--field-hover\)[data-highlighted]{background-color:var(--field-hover)}.data-\[highlighted\]\:text-accent-foreground[data-highlighted]{color:var(--accent-foreground)}.data-\[instant\]\:animate-none[data-instant]{animation:none}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[side\=bottom\]\:top-1[data-side=bottom]{top:var(--spacing)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\[side\=left\]\:top-1\/2\![data-side=left]{top:50%!important}.data-\[side\=left\]\:-right-1[data-side=left]{right:calc(var(--spacing) * -1)}.data-\[side\=left\]\:-translate-y-1\/2[data-side=left]{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\[side\=right\]\:top-1\/2\![data-side=right]{top:50%!important}.data-\[side\=right\]\:-left-1[data-side=right]{left:calc(var(--spacing) * -1)}.data-\[side\=right\]\:-translate-y-1\/2[data-side=right]{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\[side\=top\]\:-bottom-2\.5[data-side=top]{bottom:calc(var(--spacing) * -2.5)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\[state\=open\]\:opacity-100[data-state=open]{opacity:1}@media (hover:hover){.data-\[state\=open\]\:hover\:bg-sidebar-accent[data-state=open]:hover{background-color:var(--sidebar-accent)}.data-\[state\=open\]\:hover\:text-sidebar-accent-foreground[data-state=open]:hover{color:var(--sidebar-accent-foreground)}}@media (prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}@media (min-width:40rem){.sm\:max-w-sm{max-width:var(--container-sm)}}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:opacity-0{opacity:0}.md\:after\:hidden:after{content:var(--tw-content);display:none}}@media (prefers-color-scheme:dark){.dark\:border-input{border-color:var(--input)}.dark\:bg-destructive\/60{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-destructive\/60{background-color:color-mix(in oklab, var(--destructive) 60%, transparent)}}.dark\:bg-input\/30{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-input\/30{background-color:color-mix(in oklab, var(--input) 30%, transparent)}}@media (hover:hover){.dark\:hover\:bg-accent\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-accent\/50:hover{background-color:color-mix(in oklab, var(--accent) 50%, transparent)}}.dark\:hover\:bg-input\/50:hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-input\/50:hover{background-color:color-mix(in oklab, var(--input) 50%, transparent)}}}.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:focus-visible\:ring-destructive\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\:aria-invalid\:ring-destructive\/40[aria-invalid=true]{--tw-ring-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3 svg:not([class*=size-]){width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\:not\(\[class\*\=\'text-\'\]\)\]\:text-muted-foreground svg:not([class*=text-]){color:var(--muted-foreground)}.\[\&\>button\]\:hidden>button{display:none}.\[\&\>span\:first-child\]\:truncate>span:first-child,.\[\&\>span\:last-child\]\:truncate>span:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.\[\&\>svg\]\:size-3>svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}@media (hover:none){.\[\@media\(hover\:none\)\]\:translate-x-0{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.\[\@media\(hover\:none\)\]\:opacity-100{opacity:1}}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/20{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/20{background-color:color-mix(in oklab, var(--background) 20%, transparent)}}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:text-background{color:var(--background)}@media (prefers-color-scheme:dark){[data-slot=tooltip-content] .dark\:\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/10{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){[data-slot=tooltip-content] .dark\:\[\[data-slot\=tooltip-content\]_\&\]\:bg-background\/10{background-color:color-mix(in oklab, var(--background) 10%, transparent)}}}}@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}.studio-workspace{color:var(--foreground);background:var(--background);font:12px/1.5 var(--studio-font);cursor:default}.studio-workspace [data-slot=studio-config-file][href]{cursor:pointer;text-underline-offset:3px;text-decoration:none}.studio-workspace [data-slot=studio-config-file][href]:is(:hover,:focus-visible){text-decoration-line:underline}.studio-workspace [data-slot=studio-config-file][href]:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.studio-workspace :is([data-slot=sidebar-header],[data-slot=sidebar-footer]){isolation:isolate;flex-shrink:0;position:relative}.studio-workspace :is([data-slot=sidebar-header],[data-slot=sidebar-footer]):before{content:"";z-index:-1;border-radius:calc(var(--radius-lg) - .25rem);background:var(--card);pointer-events:none;position:absolute;inset:4px}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]{min-height:36px;color:var(--muted-foreground);gap:10px;font-size:13px;line-height:20px}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]>span:first-child{flex-shrink:0;display:flex}.studio-workspace [data-slot=sidebar-content] [data-slot=sidebar-menu-button]:is(:hover,:focus-visible,[data-active=true]){color:var(--sidebar-accent-foreground)}.studio-workspace{--studio-inspector-width:20rem;--preview-left:8px;--preview-right:8px;--preview-bottom:8px;position:relative}@media (min-width:768px){.studio-workspace[data-sidebar-panel=shown]{--preview-left:var(--sidebar-width)}.studio-workspace[data-sidebar-panel=shown]:has([data-slot=sidebar][data-state=collapsed]){--preview-left:calc(var(--sidebar-width-icon) + 1rem + 2px)}}@media (min-width:1024px){.studio-workspace:has([data-slot=studio-inspector][aria-hidden=false]){--preview-right:calc(var(--studio-inspector-width) + 1rem)}}@media (max-width:1023px){.studio-workspace:is(:has(>[data-slot=preview-canvas]:not([data-expanded])),[data-preview-layout=custom]):has([data-slot=studio-inspector][aria-hidden=false]){--preview-bottom:40%}.studio-workspace:is(:has(>[data-slot=preview-canvas]:not([data-expanded])),[data-preview-layout=custom]) [data-slot=studio-inspector]{inset:calc(60% + 8px) 8px 8px var(--preview-left);width:auto}}.studio-workspace>[data-slot=preview-canvas]{z-index:0}.studio-workspace>[data-slot=preview-canvas]:not([data-expanded]){inset:8px var(--preview-right) var(--preview-bottom) var(--preview-left);position:absolute}.studio-workspace>iframe[data-slot=studio-preview]{background:var(--background);border:0;width:100%;height:100%;position:absolute;inset:0}.studio-workspace[data-preview-layout=custom]>iframe[data-slot=studio-preview]{inset:0 calc(var(--preview-right) - 8px) calc(var(--preview-bottom) - 8px) calc(var(--preview-left) - 8px);width:calc(100% - var(--preview-left) - var(--preview-right) + 16px);height:calc(100% - var(--preview-bottom) + 8px)}:root{--background:#000;--foreground:#d6d7dc;--card:#ffffff0a;--card-foreground:#d6d7dc;--popover:#18191c;--popover-foreground:#d6d7dc;--primary:#e6e7ea;--primary-foreground:#000;--secondary:#ffffff14;--secondary-foreground:#d6d7dc;--muted:#18191c;--muted-foreground:#8b8c94;--faint:#5d5e66;--accent:#18191c;--accent-foreground:#d6d7dc;--destructive:#f87171;--success:#4ade80;--warning:#facc15;--border:#26272b;--input:#26272b;--ring:#5d5e66;--radius:.5rem;--field:#ffffff0f;--field-hover:#ffffff17;--field-active:#ffffff1f;--knob:#4a4b52;--knob-hover:#5a5b63;--sidebar:#000;--sidebar-foreground:#8b8c94;--sidebar-primary:#e6e7ea;--sidebar-primary-foreground:#000;--sidebar-accent:#ffffff14;--sidebar-accent-foreground:#d6d7dc;--sidebar-border:#26272b;--sidebar-ring:#5d5e66;--studio-font:ui-monospace, SFMono-Regular, Menlo, monospace;color-scheme:dark}[data-slot=studio-controls] :is(.tp-lblv_l,.tp-fldv_t):first-letter{text-transform:uppercase}[data-slot=studio-controls] .dialkit-root{--dial-glass-bg:var(--background);--dial-surface:var(--field);--dial-surface-hover:var(--field-hover);--dial-surface-active:var(--field-active);--dial-border:var(--border);--dial-text-root:var(--foreground);--dial-text-section:var(--muted-foreground);--dial-text-label:var(--muted-foreground);font-family:var(--studio-font)}@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-border-style{syntax:"*";inherits:false;initial-value:solid}@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-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-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DebugAdapter, DebugHost, TweakpaneModule } from '@joycostudio/xyz/debug';
|
|
2
|
+
import { DialKitModule, DialKitAdapterOptions } from '@joycostudio/xyz/debug/dialkit';
|
|
3
|
+
|
|
4
|
+
type Loader<T> = () => T | Promise<T>;
|
|
5
|
+
/**
|
|
6
|
+
* The debug UI library Studio draws tool controls with: Tweakpane or DialKit. Pick one with
|
|
7
|
+
* `createStudio({ ui })`; the library loads lazily through `load`, from the host app, so only
|
|
8
|
+
* the one you pick needs to be installed.
|
|
9
|
+
*/
|
|
10
|
+
type StudioUi = {
|
|
11
|
+
readonly kind: string;
|
|
12
|
+
/** The floating pane `StudioDebug` opens on `?debug` / Option+D. */
|
|
13
|
+
floating: DebugAdapter;
|
|
14
|
+
/** Controls drawn inside `container`, as the /studio inspector does. */
|
|
15
|
+
inline(container: HTMLElement, options: {
|
|
16
|
+
title: string;
|
|
17
|
+
}): Promise<DebugHost & {
|
|
18
|
+
dispose(): void;
|
|
19
|
+
}>;
|
|
20
|
+
/** Copy the library's page styles into Studio's shadow root, which page stylesheets don't reach. */
|
|
21
|
+
adoptStyles(root: ShadowRoot): void | Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Draw controls with [Tweakpane](https://tweakpane.github.io/docs/):
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* createStudio({ tools, ui: tweakpane(() => import('tweakpane')) })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
declare function tweakpane(load: Loader<TweakpaneModule>): StudioUi;
|
|
31
|
+
/**
|
|
32
|
+
* Draw controls with [DialKit](https://github.com/joshpuckett/dialkit). Import its stylesheet once in the app too:
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* import 'dialkit/vanilla/styles.css'
|
|
36
|
+
* createStudio({ tools, ui: dialkit(() => import('dialkit/vanilla')) })
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* `options` apply to the floating `StudioDebug` pane (e.g. `position`); the inspector is always inline.
|
|
40
|
+
*/
|
|
41
|
+
declare function dialkit(load: Loader<DialKitModule>, options?: DialKitAdapterOptions): StudioUi;
|
|
42
|
+
|
|
43
|
+
export { type StudioUi, dialkit, tweakpane };
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/ui.ts
|
|
2
|
+
import {
|
|
3
|
+
tweakpane as tweakpaneAdapter,
|
|
4
|
+
tweakpaneHost
|
|
5
|
+
} from "@joycostudio/xyz/debug";
|
|
6
|
+
import {
|
|
7
|
+
dialkit as dialkitAdapter,
|
|
8
|
+
dialkitHost
|
|
9
|
+
} from "@joycostudio/xyz/debug/dialkit";
|
|
10
|
+
async function rulesOf(sheet) {
|
|
11
|
+
try {
|
|
12
|
+
return sheet.cssRules;
|
|
13
|
+
} catch {
|
|
14
|
+
if (!sheet.href) return null;
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(sheet.href, { mode: "cors", credentials: "omit" });
|
|
17
|
+
if (!response.ok) return null;
|
|
18
|
+
const copy = new CSSStyleSheet();
|
|
19
|
+
copy.replaceSync(await response.text());
|
|
20
|
+
return copy.cssRules;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
var adopting = /* @__PURE__ */ new WeakMap();
|
|
27
|
+
async function adoptRules(root, id, test) {
|
|
28
|
+
const ids = adopting.get(root) ?? /* @__PURE__ */ new Set();
|
|
29
|
+
adopting.set(root, ids);
|
|
30
|
+
if (ids.has(id)) return;
|
|
31
|
+
ids.add(id);
|
|
32
|
+
let css = "";
|
|
33
|
+
let unreadable = 0;
|
|
34
|
+
for (const rules of await Promise.all([...document.styleSheets].map(rulesOf))) {
|
|
35
|
+
if (!rules) unreadable++;
|
|
36
|
+
else for (const rule of rules) if (test(rule.cssText)) css += rule.cssText;
|
|
37
|
+
}
|
|
38
|
+
if (!css) {
|
|
39
|
+
ids.delete(id);
|
|
40
|
+
console.warn(
|
|
41
|
+
`[studio] No ${id} styles reached the inspector. Import ${id}'s stylesheet in the app` + (unreadable ? `; ${unreadable} cross-origin stylesheet(s) could not be read (serve them with CORS headers).` : ".")
|
|
42
|
+
);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const style = document.createElement("style");
|
|
46
|
+
style.dataset.studioAdopted = id;
|
|
47
|
+
style.textContent = css;
|
|
48
|
+
root.prepend(style);
|
|
49
|
+
}
|
|
50
|
+
function tweakpane(load) {
|
|
51
|
+
return {
|
|
52
|
+
kind: "tweakpane",
|
|
53
|
+
floating: tweakpaneAdapter(load, { title: "debug" }),
|
|
54
|
+
async inline(container) {
|
|
55
|
+
const { Pane } = await load();
|
|
56
|
+
return tweakpaneHost(new Pane({ container }));
|
|
57
|
+
},
|
|
58
|
+
// Tweakpane (and its plugins) inject `<style data-tp-style>` into the head; Tweakpane skips ids it already injected.
|
|
59
|
+
adoptStyles(root) {
|
|
60
|
+
for (const style of document.head.querySelectorAll("style[data-tp-style]")) {
|
|
61
|
+
if (!root.querySelector(`style[data-tp-style="${style.dataset.tpStyle}"]`)) root.append(style.cloneNode(true));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function dialkit(load, options = {}) {
|
|
67
|
+
return {
|
|
68
|
+
kind: "dialkit",
|
|
69
|
+
floating: dialkitAdapter(load, options),
|
|
70
|
+
async inline(container, { title }) {
|
|
71
|
+
return dialkitHost(await load(), { ...options, title, mode: "inline", theme: "dark", target: container });
|
|
72
|
+
},
|
|
73
|
+
adoptStyles: (root) => adoptRules(root, "dialkit", (css) => css.includes("dialkit") || css.includes("--dial-"))
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
dialkit,
|
|
78
|
+
tweakpane
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui.ts"],"sourcesContent":["import {\n tweakpane as tweakpaneAdapter,\n tweakpaneHost,\n type DebugAdapter,\n type DebugHost,\n type TweakpaneModule,\n} from '@joycostudio/xyz/debug'\nimport {\n dialkit as dialkitAdapter,\n dialkitHost,\n type DialKitAdapterOptions,\n type DialKitModule,\n} from '@joycostudio/xyz/debug/dialkit'\n\ntype Loader<T> = () => T | Promise<T>\n\n/**\n * The debug UI library Studio draws tool controls with: Tweakpane or DialKit. Pick one with\n * `createStudio({ ui })`; the library loads lazily through `load`, from the host app, so only\n * the one you pick needs to be installed.\n */\nexport type StudioUi = {\n readonly kind: string\n /** The floating pane `StudioDebug` opens on `?debug` / Option+D. */\n floating: DebugAdapter\n /** Controls drawn inside `container`, as the /studio inspector does. */\n inline(container: HTMLElement, options: { title: string }): Promise<DebugHost & { dispose(): void }>\n /** Copy the library's page styles into Studio's shadow root, which page stylesheets don't reach. */\n adoptStyles(root: ShadowRoot): void | Promise<void>\n}\n\n/** A stylesheet's rules. Cross-origin sheets (a CDN `assetPrefix`) hide theirs, so fetch those over CORS. */\nasync function rulesOf(sheet: CSSStyleSheet): Promise<CSSRuleList | null> {\n try {\n return sheet.cssRules\n } catch {\n if (!sheet.href) return null\n try {\n const response = await fetch(sheet.href, { mode: 'cors', credentials: 'omit' })\n if (!response.ok) return null\n const copy = new CSSStyleSheet()\n copy.replaceSync(await response.text())\n return copy.cssRules\n } catch {\n return null\n }\n }\n}\n\nconst adopting = new WeakMap<ShadowRoot, Set<string>>()\n\n/** Copy page-level CSS rules matching `test` into `root`, once per root. */\nasync function adoptRules(root: ShadowRoot, id: string, test: (css: string) => boolean) {\n const ids = adopting.get(root) ?? new Set()\n adopting.set(root, ids)\n if (ids.has(id)) return\n ids.add(id)\n let css = ''\n let unreadable = 0\n for (const rules of await Promise.all([...document.styleSheets].map(rulesOf))) {\n if (!rules) unreadable++\n else for (const rule of rules) if (test(rule.cssText)) css += rule.cssText\n }\n if (!css) {\n ids.delete(id) // Try again on the next mount, in case the stylesheet loads later.\n console.warn(\n `[studio] No ${id} styles reached the inspector. Import ${id}'s stylesheet in the app` +\n (unreadable\n ? `; ${unreadable} cross-origin stylesheet(s) could not be read (serve them with CORS headers).`\n : '.'),\n )\n return\n }\n const style = document.createElement('style')\n style.dataset.studioAdopted = id\n style.textContent = css\n root.prepend(style)\n}\n\n/**\n * Draw controls with [Tweakpane](https://tweakpane.github.io/docs/):\n *\n * ```ts\n * createStudio({ tools, ui: tweakpane(() => import('tweakpane')) })\n * ```\n */\nexport function tweakpane(load: Loader<TweakpaneModule>): StudioUi {\n return {\n kind: 'tweakpane',\n floating: tweakpaneAdapter(load, { title: 'debug' } as never),\n async inline(container) {\n const { Pane } = await load()\n return tweakpaneHost(new Pane({ container } as never))\n },\n // Tweakpane (and its plugins) inject `<style data-tp-style>` into the head; Tweakpane skips ids it already injected.\n adoptStyles(root) {\n for (const style of document.head.querySelectorAll<HTMLStyleElement>('style[data-tp-style]')) {\n if (!root.querySelector(`style[data-tp-style=\"${style.dataset.tpStyle}\"]`)) root.append(style.cloneNode(true))\n }\n },\n }\n}\n\n/**\n * Draw controls with [DialKit](https://github.com/joshpuckett/dialkit). Import its stylesheet once in the app too:\n *\n * ```ts\n * import 'dialkit/vanilla/styles.css'\n * createStudio({ tools, ui: dialkit(() => import('dialkit/vanilla')) })\n * ```\n *\n * `options` apply to the floating `StudioDebug` pane (e.g. `position`); the inspector is always inline.\n */\nexport function dialkit(load: Loader<DialKitModule>, options: DialKitAdapterOptions = {}): StudioUi {\n return {\n kind: 'dialkit',\n floating: dialkitAdapter(load, options),\n async inline(container, { title }) {\n // Dark, like the rest of Studio; styles.css maps its palette onto Studio's.\n return dialkitHost(await load(), { ...options, title, mode: 'inline', theme: 'dark', target: container })\n },\n adoptStyles: (root) => adoptRules(root, 'dialkit', (css) => css.includes('dialkit') || css.includes('--dial-')),\n }\n}\n"],"mappings":";AAAA;AAAA,EACE,aAAa;AAAA,EACb;AAAA,OAIK;AACP;AAAA,EACE,WAAW;AAAA,EACX;AAAA,OAGK;AAoBP,eAAe,QAAQ,OAAmD;AACxE,MAAI;AACF,WAAO,MAAM;AAAA,EACf,QAAQ;AACN,QAAI,CAAC,MAAM,KAAM,QAAO;AACxB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,MAAM,MAAM,EAAE,MAAM,QAAQ,aAAa,OAAO,CAAC;AAC9E,UAAI,CAAC,SAAS,GAAI,QAAO;AACzB,YAAM,OAAO,IAAI,cAAc;AAC/B,WAAK,YAAY,MAAM,SAAS,KAAK,CAAC;AACtC,aAAO,KAAK;AAAA,IACd,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,IAAM,WAAW,oBAAI,QAAiC;AAGtD,eAAe,WAAW,MAAkB,IAAY,MAAgC;AACtF,QAAM,MAAM,SAAS,IAAI,IAAI,KAAK,oBAAI,IAAI;AAC1C,WAAS,IAAI,MAAM,GAAG;AACtB,MAAI,IAAI,IAAI,EAAE,EAAG;AACjB,MAAI,IAAI,EAAE;AACV,MAAI,MAAM;AACV,MAAI,aAAa;AACjB,aAAW,SAAS,MAAM,QAAQ,IAAI,CAAC,GAAG,SAAS,WAAW,EAAE,IAAI,OAAO,CAAC,GAAG;AAC7E,QAAI,CAAC,MAAO;AAAA,QACP,YAAW,QAAQ,MAAO,KAAI,KAAK,KAAK,OAAO,EAAG,QAAO,KAAK;AAAA,EACrE;AACA,MAAI,CAAC,KAAK;AACR,QAAI,OAAO,EAAE;AACb,YAAQ;AAAA,MACN,eAAe,EAAE,yCAAyC,EAAE,8BACzD,aACG,KAAK,UAAU,kFACf;AAAA,IACR;AACA;AAAA,EACF;AACA,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,cAAc;AACpB,OAAK,QAAQ,KAAK;AACpB;AASO,SAAS,UAAU,MAAyC;AACjE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,iBAAiB,MAAM,EAAE,OAAO,QAAQ,CAAU;AAAA,IAC5D,MAAM,OAAO,WAAW;AACtB,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK;AAC5B,aAAO,cAAc,IAAI,KAAK,EAAE,UAAU,CAAU,CAAC;AAAA,IACvD;AAAA;AAAA,IAEA,YAAY,MAAM;AAChB,iBAAW,SAAS,SAAS,KAAK,iBAAmC,sBAAsB,GAAG;AAC5F,YAAI,CAAC,KAAK,cAAc,wBAAwB,MAAM,QAAQ,OAAO,IAAI,EAAG,MAAK,OAAO,MAAM,UAAU,IAAI,CAAC;AAAA,MAC/G;AAAA,IACF;AAAA,EACF;AACF;AAYO,SAAS,QAAQ,MAA6B,UAAiC,CAAC,GAAa;AAClG,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,eAAe,MAAM,OAAO;AAAA,IACtC,MAAM,OAAO,WAAW,EAAE,MAAM,GAAG;AAEjC,aAAO,YAAY,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,OAAO,MAAM,UAAU,OAAO,QAAQ,QAAQ,UAAU,CAAC;AAAA,IAC1G;AAAA,IACA,aAAa,CAAC,SAAS,WAAW,MAAM,WAAW,CAAC,QAAQ,IAAI,SAAS,SAAS,KAAK,IAAI,SAAS,SAAS,CAAC;AAAA,EAChH;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joycostudio/studio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Plug project-specific tools into a /studio route, a floating debug pane, and MCP agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|
|
@@ -47,6 +47,10 @@
|
|
|
47
47
|
"types": "./dist/controls.d.ts",
|
|
48
48
|
"default": "./dist/controls.js"
|
|
49
49
|
},
|
|
50
|
+
"./ui": {
|
|
51
|
+
"types": "./dist/ui.d.ts",
|
|
52
|
+
"default": "./dist/ui.js"
|
|
53
|
+
},
|
|
50
54
|
"./next/config": {
|
|
51
55
|
"types": "./dist/next-config.d.ts",
|
|
52
56
|
"default": "./dist/next-config.js"
|
|
@@ -71,7 +75,8 @@
|
|
|
71
75
|
"typescript": "^5.9.3"
|
|
72
76
|
},
|
|
73
77
|
"peerDependencies": {
|
|
74
|
-
"@joycostudio/xyz": "^1.
|
|
78
|
+
"@joycostudio/xyz": "^1.5.0",
|
|
79
|
+
"dialkit": "^2.2.0",
|
|
75
80
|
"react": ">=18",
|
|
76
81
|
"react-dom": ">=18",
|
|
77
82
|
"tweakpane": "^4.0.5"
|
|
@@ -85,10 +90,13 @@
|
|
|
85
90
|
},
|
|
86
91
|
"react-dom": {
|
|
87
92
|
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"dialkit": {
|
|
95
|
+
"optional": true
|
|
88
96
|
}
|
|
89
97
|
},
|
|
90
98
|
"devDependencies": {
|
|
91
|
-
"@joycostudio/xyz": "^1.
|
|
99
|
+
"@joycostudio/xyz": "^1.5.0",
|
|
92
100
|
"@modelcontextprotocol/client": "^2.3.1",
|
|
93
101
|
"@tailwindcss/cli": "^4.3.3",
|
|
94
102
|
"@tweakpane/core": "^2.0.5",
|
|
@@ -96,6 +104,7 @@
|
|
|
96
104
|
"@types/react": "^19.3.0",
|
|
97
105
|
"@types/react-dom": "^19.3.0",
|
|
98
106
|
"@types/ws": "^8.18.2",
|
|
107
|
+
"dialkit": "^2.2.0",
|
|
99
108
|
"react": "^19.3.0",
|
|
100
109
|
"react-dom": "^19.3.0",
|
|
101
110
|
"tailwindcss": "^4.3.3",
|
|
@@ -111,7 +120,7 @@
|
|
|
111
120
|
"build": "pnpm build:shadow-css && tsup && tailwindcss -i src/react/styles.css -o dist/styles.css --minify && cp src/react/command-menu-export.css dist/command-menu.css",
|
|
112
121
|
"dev": "pnpm build:shadow-css && pnpm run --parallel \"/^dev:/\"",
|
|
113
122
|
"test": "vitest run",
|
|
114
|
-
"test:browser": "STUDIO_TEST_BROWSER=1 vitest run test/browser-sync.test.ts",
|
|
123
|
+
"test:browser": "STUDIO_TEST_BROWSER=1 vitest run test/browser-sync.test.ts test/ui.test.ts",
|
|
115
124
|
"test:capture": "STUDIO_TEST_CAPTURE=1 vitest run test/capture.test.ts",
|
|
116
125
|
"typecheck": "tsc --noEmit",
|
|
117
126
|
"dev:js": "tsup --watch",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/tool.ts","../src/core/result.ts","../src/core/validate.ts"],"sourcesContent":["import type { DebugSchema } from '@joycostudio/xyz/debug'\n\n/**\n * An SVG icon as data: `[tag, attributes]` children of a 24×24 stroke icon.\n * Lucide's core package (`import { Palette } from 'lucide'`) exports exactly this shape.\n */\nexport type ToolIcon = readonly (readonly [tag: string, attrs: Record<string, string | number | undefined>])[]\n\ntype ToolBase = {\n /** Unique, URL-safe identifier. */\n id: string\n title?: string\n /** Shown next to the tool in /studio. Data, not a component, so contracts stay loadable in Node. */\n icon?: ToolIcon\n /** App route that renders this tool's result, shown next to the controls in /studio. */\n preview?: string\n /** Use a bare iframe for tools that already own their canvas layout and headers. */\n previewLayout?: 'canvas' | 'custom'\n}\n\n/**\n * A tool's contract. Isomorphic on purpose: the runtime loads it in Node to\n * validate and persist, the app loads it in the browser to apply and debug.\n *\n * `TConfig` is the one type that is read, edited, applied, and persisted.\n */\nexport type ToolDefinition<TConfig extends object = object> = ToolBase & {\n /** Repo-relative JSON file the config persists to. Import that same file as `initial`. */\n file: string\n /** Config used before the runtime answers (and in production). */\n initial: TConfig\n /**\n * What can be tweaked, as an Xyz/Tweakpane schema bound to `config`.\n * Doubles as the runtime validator: every control's bounds are enforced on write.\n */\n controls: (config: TConfig) => DebugSchema\n}\n\n/** A tool with nothing to tune: a sidebar entry for its preview, without an inspector or config file. */\nexport type PreviewToolDefinition = ToolBase & {\n preview: string\n file?: never\n initial?: never\n controls?: never\n}\n\n/** A tool with a config. */\nexport type AnyTool = ToolDefinition<any>\n\n/** Anything `defineTool` returns: the kind follows from whether it declares a config. */\nexport type StudioTool = AnyTool | PreviewToolDefinition\n\nexport const hasConfig = (tool: StudioTool): tool is AnyTool => tool.controls !== undefined\n\n/** Filled by .studio/types.generated.ts in each consuming project. */\nexport interface DiscoveredToolConfigs {}\n\n/** A discovered declaration is resolved into a full definition by the generated registry. */\nexport type DiscoveredToolDefinition<TConfig extends object = object> = ToolBase & {\n /** JSON source relative to this tool file, or a tsconfig path alias. Defaults to ./config.json. */\n config?: string\n controls: (config: TConfig) => DebugSchema\n file?: never\n initial?: never\n}\nexport type ToolReference<TConfig extends object> = Pick<ToolDefinition<TConfig>, 'id' | 'controls'>\nexport type ConfigOf<TTool> = TTool extends ToolReference<infer TConfig> ? TConfig : never\n\nconst ID = /^[a-z0-9][a-z0-9-]*$/\n\n/** Discovered tools infer their config from the generated ID-to-JSON type map. */\nexport function defineTool<K extends keyof DiscoveredToolConfigs & string>(\n tool: Omit<DiscoveredToolDefinition<Extract<DiscoveredToolConfigs[K], object>>, 'id'> & { id: K },\n): DiscoveredToolDefinition<Extract<DiscoveredToolConfigs[K], object>>\n/** Existing explicitly registered tools remain supported. */\nexport function defineTool<TConfig extends object>(tool: ToolDefinition<TConfig>): ToolDefinition<TConfig>\nexport function defineTool(tool: PreviewToolDefinition): PreviewToolDefinition\n/** A discovered preview-only tool may infer its preview from the adjacent page. */\nexport function defineTool(\n tool: ToolBase & { controls?: never; config?: never; file?: never; initial?: never },\n): ToolBase\nexport function defineTool(tool: StudioTool | DiscoveredToolDefinition<any> | ToolBase) {\n if (!ID.test(tool.id)) throw new Error(`[studio] tool id \"${tool.id}\" must be kebab-case`)\n const value = tool as Partial<AnyTool>\n if (value.file !== undefined || value.initial !== undefined) {\n if (value.file === undefined || value.initial === undefined || value.controls === undefined)\n throw new Error(`[studio] tool \"${tool.id}\" needs all of file, initial, and controls, or none of them`)\n }\n return tool\n}\n\nexport type StudioConfig = {\n /** Explicit registry; omit to enable convention-based discovery. */\n tools?: readonly StudioTool[]\n /**\n * Directory to scan and watch for `studio.tool.ts` files, relative to\n * the project root.\n *\n * Defaults to the active Next.js app directory: `app/` or `src/app/`.\n * Set a narrower directory to reduce scanning and discovery triggers.\n * This does not change preview URLs.\n *\n * @example 'src/app/experiments'\n */\n toolsDir?: string\n /** Runtime WebSocket and HTTP MCP port. Defaults to 5179. */\n port?: number\n /** Browser origins allowed on the bridge and MCP endpoint. Defaults to localhost origins. */\n origins?: readonly string[]\n /** Running app URL (e.g. http://localhost:3000), used for MCP preview captures. */\n appUrl?: string\n}\n\nexport const DEFAULT_PORT = 5179\n\nexport function defineConfig<T extends StudioConfig>(config: T): T {\n return config\n}\n","export type Success<T> = { ok: true; data: T }\n\nexport type Failure = {\n ok: false\n /** snake_case wire code, e.g. `invalid_config`. */\n error: string\n message?: string\n}\n\nexport type Result<T> = Success<T> | Failure\n\nexport const success = <T>(data: T): Success<T> => ({ ok: true, data })\n\nexport const error = (code: string, message?: string): Failure => ({\n ok: false,\n error: code,\n ...(message === undefined ? {} : { message }),\n})\n","import type { DebugSchema } from '@joycostudio/xyz/debug'\nimport { error, success, type Result } from './result'\nimport type { ToolDefinition } from './tool'\n\n/**\n * Accept `candidate` as a config for `tool` only if it has the exact shape of\n * `tool.initial` and every control in `tool.controls` accepts its value.\n * Returns a detached copy, never the input.\n */\nexport function validateConfig<TConfig extends object>(\n tool: ToolDefinition<TConfig>,\n candidate: unknown,\n): Result<TConfig> {\n const mismatch = shapeMismatch(tool.initial, candidate, 'config')\n if (mismatch) return error('invalid_config', mismatch)\n const config = structuredClone(candidate) as TConfig\n const invalid = invalidControl(tool.controls(config))\n return invalid ? error('invalid_config', invalid) : success(config)\n}\n\nfunction kind(value: unknown) {\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'array'\n return typeof value\n}\n\nfunction shapeMismatch(reference: unknown, value: unknown, path: string): string | null {\n const expected = kind(reference)\n if (kind(value) !== expected) return `${path}: expected ${expected}, got ${kind(value)}`\n if (expected === 'number' && !Number.isFinite(value)) return `${path}: expected a finite number`\n if (expected === 'array') {\n const [first] = reference as unknown[]\n if (first === undefined) return null\n for (const [index, item] of (value as unknown[]).entries()) {\n const nested = shapeMismatch(first, item, `${path}[${index}]`)\n if (nested) return nested\n }\n }\n if (expected === 'object') {\n const ref = reference as Record<string, unknown>\n const obj = value as Record<string, unknown>\n for (const key of Object.keys(obj)) if (!(key in ref)) return `${path}.${key}: unknown key`\n for (const key of Object.keys(ref)) {\n if (!(key in obj)) return `${path}.${key}: missing`\n const nested = shapeMismatch(ref[key], obj[key], `${path}.${key}`)\n if (nested) return nested\n }\n }\n return null\n}\n\nconst isRgb = (value: unknown) =>\n typeof value === 'object' &&\n value !== null &&\n ['r', 'g', 'b'].every((channel) => Number.isFinite((value as Record<string, unknown>)[channel]))\n\nfunction invalidControl(schema: DebugSchema, path = ''): string | null {\n for (const [key, field] of Object.entries(schema)) {\n if (field.kind === 'button') continue\n const name = `${path}${field.label ?? key}`\n if (field.kind === 'folder') {\n const nested = invalidControl(field.definition.schema(), `${name}/`)\n if (nested) return nested\n continue\n }\n const value: unknown = field.read()\n if (field.kind === 'slider') {\n if (typeof value !== 'number' || value < field.min || value > field.max)\n return `${name}: expected a number in [${field.min}, ${field.max}], got ${JSON.stringify(value)}`\n } else if (field.kind === 'bool') {\n if (typeof value !== 'boolean') return `${name}: expected a boolean`\n } else if (field.kind === 'select') {\n const options = Object.values(field.options)\n if (!options.includes(value as string | number))\n return `${name}: expected one of ${JSON.stringify(options)}, got ${JSON.stringify(value)}`\n } else if (field.kind === 'color-string') {\n if (typeof value !== 'string') return `${name}: expected a color string`\n } else if (field.kind === 'color') {\n if (!isRgb(value)) return `${name}: expected an { r, g, b } color`\n }\n }\n return null\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/studio.ts","../src/core/diff.ts","../src/client/bridge.ts","../src/client/browser-sync.ts","../src/client/history.ts","../src/client/live.ts"],"sourcesContent":["import {\n button,\n type DebugDefinition,\n type DebugField,\n type DebugFolder,\n type DebugSchema,\n schemaValues,\n} from '@joycostudio/xyz/debug'\nimport { changedPaths } from '../core/diff'\nimport type { ToolState } from '../core/protocol'\nimport { error, type Result } from '../core/result'\nimport { hasConfig, type StudioTool, type ToolDefinition, type ToolReference } from '../core/tool'\nimport { connectBridge, type BridgeClient, type Connection } from './bridge'\nimport { connectBrowserSync } from './browser-sync'\nimport { createHistory, writePath } from './history'\nimport { assignDeep, live } from './live'\n\nexport type ToolHandle<TConfig extends object = any> = {\n readonly definition: ToolDefinition<TConfig>\n /** The live config. Writes sync to same-origin pages and, when connected, the runtime. */\n readonly config: TConfig\n /** Runtime-owned state; null while no runtime is connected or until it answers. */\n readonly state: ToolState<TConfig> | null\n /** Bumps on every config change. Handy as a React snapshot. */\n readonly version: number\n /** Called after every config change, local or remote. */\n subscribe(listener: (config: TConfig) => void): () => void\n /** The tool's Xyz schema bound to the live config. */\n controls(): DebugSchema\n /** Xyz `Debuggable`: `debugManager.register(handle)` mounts this tool in the app's floating pane. */\n debug(): DebugFolder\n /** The config on disk: the runtime's last reported saved value or, until one answers, the bundled `initial`. */\n readonly saved: TConfig\n /** Dotted paths where the draft differs from `saved`. Tracked locally, so it works without a runtime too. */\n readonly changes: string[]\n /** The draft differs from `saved`. */\n readonly dirty: boolean\n /** True while `compare(true)` shows the saved config in place of the draft. */\n readonly comparing: boolean\n /**\n * Temporarily show `saved` (true) or go back to the draft (false). Local only: nothing\n * reaches the runtime, and edits made while comparing are dropped when it ends.\n */\n compare(showSaved: boolean): void\n /** True when `undo()` has an edit made on this page to step back through. */\n readonly canUndo: boolean\n readonly canRedo: boolean\n /**\n * Step back through edits made on this page (a slider drag counts as one), then sync the result like any\n * other edit. Only the leaves each edit changed are restored. Returns false with nothing to undo or while comparing.\n */\n undo(): boolean\n redo(): boolean\n /** Persist the draft. Needs a connected runtime. */\n save(options?: { force?: boolean }): Promise<Result<ToolState<TConfig>>>\n /**\n * Reset the draft to `saved`, with or without a runtime, then sync it like any other edit.\n * Undoable as its own step. Returns false when there is nothing to discard.\n */\n discard(): boolean\n}\n\nexport type Studio = {\n /** Every registered tool in order, including preview-only ones. */\n readonly definitions: readonly StudioTool[]\n /** A handle per tool with a config. Preview-only tools have none. */\n readonly tools: readonly ToolHandle[]\n tool<TConfig extends object>(definition: ToolReference<TConfig>): ToolHandle<TConfig>\n readonly connection: Connection\n /** Bumps on connection or any tool state change. */\n readonly version: number\n subscribe(listener: () => void): () => void\n close(): void\n}\n\nexport type StudioOptions = {\n tools: readonly StudioTool[]\n /**\n * Runtime bridge URL (e.g. `ws://127.0.0.1:5179`). Omit or pass false for browser-only syncing, as in production.\n * Only browsers connect, so a module-scope `createStudio` is safe to evaluate during SSR.\n */\n runtime?: string | false\n}\n\nconst COMPARE_MESSAGE = 'joyco-studio:compare'\ntype CompareMessage = { type: typeof COMPARE_MESSAGE; tool: string; showSaved: boolean }\n\n/** Make the studio running in `target` (e.g. a preview iframe) compare `tool` as well. */\nexport function postCompare(target: Window | null | undefined, tool: string, showSaved: boolean) {\n const message: CompareMessage = { type: COMPARE_MESSAGE, tool, showSaved }\n target?.postMessage(message, location.origin)\n}\n\n/** Mark every value control live so a pane registered with `registerFrame` reflects remote edits. */\nfunction liveSchema(schema: DebugSchema): DebugSchema {\n return Object.fromEntries(\n Object.entries(schema).map(([key, field]): [string, DebugField] => {\n if (field.kind === 'button') return [key, field]\n if (field.kind === 'folder')\n return [\n key,\n { ...field, definition: { ...field.definition, schema: () => liveSchema(field.definition.schema()) } },\n ]\n return [key, { ...field, live: true }]\n }),\n )\n}\n\n/**\n * Xyz `extend` for a folder bound to `handle.controls()` (optionally followed by more fields, as in `debug()`):\n * double-clicking a slider resets it to its saved value.\n */\nexport function resetSlidersOnDoubleClick(handle: ToolHandle): NonNullable<DebugDefinition['extend']> {\n return (folder, { fields }) => {\n const sliders = fields().filter(({ field }) => field.kind === 'slider')\n const onDoubleClick = (event: MouseEvent) => {\n // Double-clicking the number input selects its text instead.\n if (handle.comparing || (event.target as Element).closest('input')) return\n const slider = sliders.find(({ blade }) => blade.element.contains(event.target as Node))\n if (slider?.field.kind !== 'slider') return\n const saved = slider.path.reduce<unknown>(\n (values, key) => (values as Record<string, unknown> | undefined)?.[key],\n schemaValues(handle.definition.controls(structuredClone(handle.saved))),\n )\n if (typeof saved === 'number') slider.field.write(saved)\n }\n folder.element.addEventListener('dblclick', onDoubleClick)\n return () => folder.element.removeEventListener('dblclick', onDoubleClick)\n }\n}\n\n/** A `registerFrame` for Xyz's `DebugManager` / `bindDebugSchema`: refreshes live controls every animation frame. */\nexport function everyFrame(refresh: () => void) {\n let frame = requestAnimationFrame(function tick() {\n refresh()\n frame = requestAnimationFrame(tick)\n })\n return () => cancelAnimationFrame(frame)\n}\n\n/** One studio per runtime URL (or local tool set) per page; replace HMR instances without leaking transports. */\nconst instances: Map<string, Studio> = ((globalThis as { __joycoStudio?: Map<string, Studio> }).__joycoStudio ??=\n new Map())\n\nexport function createStudio(config: StudioOptions, options: Pick<StudioOptions, 'runtime'> = {}): Studio {\n const { tools } = config\n const runtime = options.runtime ?? config.runtime\n const instanceKey = runtime || JSON.stringify(tools.map(({ id, file }) => [id, file]).sort())\n let bridge: BridgeClient | null = null\n let connection: Connection = { phase: runtime ? 'connecting' : 'local' }\n let version = 0\n const studioListeners = new Set<() => void>()\n const touch = () => {\n version++\n for (const listener of studioListeners) listener()\n }\n\n /**\n * Who owns drafts: the runtime while connected, otherwise same-origin pages share them over BroadcastChannel.\n * The only place a draft change depends on the connection; reconnecting hands ownership back to the runtime.\n */\n const runtimeOwnsDrafts = () => connection.phase === 'connected'\n\n const createHandle = <TConfig extends object>(definition: ToolDefinition<TConfig>) => {\n const raw = structuredClone(definition.initial)\n const listeners = new Set<(config: TConfig) => void>()\n let pushing: Promise<unknown> = Promise.resolve()\n let scheduled = false\n /** The last saved config the runtime reported, kept while it is away; the bundled `initial` until one answers. */\n let saved: TConfig = definition.initial\n /** The draft to restore while comparing; null when showing the draft. */\n let stashed: TConfig | null = null\n const history = createHistory()\n /** A copy of `raw` as of the last change, so the next local edit can be diffed against it. */\n let snapshot = structuredClone(raw)\n /** The draft, even while `raw` shows the saved config for comparing. */\n const draft = () => stashed ?? raw\n\n const changed = () => {\n snapshot = structuredClone(raw)\n handle.version++\n for (const listener of listeners) listener(handle.config)\n touch()\n }\n const adopt = (state: ToolState) => {\n handle.state = state as ToolState<TConfig>\n saved = state.saved.value as TConfig\n touch()\n }\n /** Replace the whole draft. While comparing, the shown saved config stays put; `changes` reads the new draft. */\n const replace = (value: TConfig) => {\n if (stashed) {\n stashed = structuredClone(value)\n touch()\n } else {\n assignDeep(raw as Record<string, unknown>, value as Record<string, unknown>)\n changed()\n }\n }\n const push = () => {\n if (scheduled || !bridge) return\n scheduled = true\n pushing = Promise.resolve().then(async () => {\n scheduled = false\n const result = await bridge?.request('tool.update', { tool: definition.id, value: draft() })\n if (!result) return\n if (result.ok) adopt(result.data)\n else if (result.error !== 'runtime_unavailable') {\n console.warn(`[studio] ${definition.id}: ${result.message ?? result.error}`)\n await resync()\n }\n })\n }\n /**\n * Send a local draft change on: to the runtime while it owns drafts. Same-origin pages always get a copy,\n * so one opened after the runtime stops starts from it, but they only read it while no runtime is connected.\n */\n const sync = () => {\n browserSync?.publish(draft())\n if (runtimeOwnsDrafts()) push()\n }\n /** The runtime's state, from a broadcast or a reply. */\n const receive = (state: ToolState) => {\n adopt(state)\n replace(state.draft.value as TConfig)\n browserSync?.publish(draft())\n }\n const resync = async () => {\n const result = await bridge?.request('tool.get', { tool: definition.id })\n if (result?.ok) receive(result.data)\n }\n /** Every local change to the live config. */\n const edited = () => {\n // Edits made while comparing stay on this page and are dropped when it ends.\n if (stashed) return changed()\n history.record(snapshot, raw)\n changed()\n sync()\n }\n const restore = (patch: ReturnType<typeof history.undo>) => {\n if (!patch) return false\n for (const { path, value } of patch) writePath(raw as Record<string, unknown>, path, value)\n changed()\n sync()\n return true\n }\n\n const handle = {\n definition,\n config: live(raw, edited),\n state: null as ToolState<TConfig> | null,\n version: 0,\n get saved(): TConfig {\n return saved\n },\n get changes() {\n return changedPaths(saved, draft())\n },\n get dirty() {\n return handle.changes.length > 0\n },\n comparing: false,\n compare(showSaved: boolean) {\n if (showSaved === handle.comparing) return\n if (showSaved) stashed = structuredClone(raw)\n const next = showSaved ? saved : stashed!\n assignDeep(raw as Record<string, unknown>, next as Record<string, unknown>)\n if (!showSaved) stashed = null\n handle.comparing = showSaved\n changed()\n },\n get canUndo() {\n return history.canUndo\n },\n get canRedo() {\n return history.canRedo\n },\n undo: () => !stashed && restore(history.undo()),\n redo: () => !stashed && restore(history.redo()),\n subscribe(listener: (config: TConfig) => void) {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n },\n controls: () => definition.controls(handle.config),\n debug(): DebugFolder {\n const actions: DebugSchema = {\n ...(runtime ? { save: button('Save', () => handle.save().then(fail), 'Saved ✓') } : {}),\n discard: button('Discard', () => void handle.discard(), 'Discarded'),\n }\n return {\n title: definition.title ?? definition.id,\n schema: () => ({ ...liveSchema(handle.controls()), ...actions }),\n extend: resetSlidersOnDoubleClick(handle),\n }\n },\n async save({ force = false } = {}) {\n if (!bridge) return error('runtime_unavailable')\n await pushing\n const revision = handle.state?.draft.revision\n if (revision === undefined) return error('runtime_unavailable')\n const result = await bridge.request('tool.save', { tool: definition.id, revision, force })\n if (result.ok) adopt(result.data)\n return result as Result<ToolState<TConfig>>\n },\n discard() {\n if (!handle.dirty) return false\n const before = snapshot\n replace(saved)\n // Undoable, as a step of its own.\n if (!stashed) history.record(before, raw, { merge: false })\n sync()\n return true\n },\n /** Connection changes: the runtime's draft wins on (re)connect; without one there is no runtime state. */\n connection() {\n if (runtimeOwnsDrafts()) return void resync()\n handle.state = null\n },\n receive,\n close: () => browserSync?.close(),\n }\n const browserSync = connectBrowserSync(definition, runtime, {\n enabled: () => !runtimeOwnsDrafts(),\n receive: replace,\n })\n return handle\n }\n\n const handles = new Map(tools.filter(hasConfig).map((definition) => [definition.id, createHandle(definition)]))\n\n // /studio asks its same-origin preview iframe to compare too (see `postCompare`).\n const onMessage = (event: MessageEvent) => {\n const message = event.data as CompareMessage | undefined\n if (event.origin !== location.origin || message?.type !== COMPARE_MESSAGE) return\n handles.get(message.tool)?.compare(message.showSaved)\n }\n if (typeof window !== 'undefined') window.addEventListener?.('message', onMessage)\n\n if (runtime && typeof window !== 'undefined') {\n bridge = connectBridge(runtime, {\n state: (state) => handles.get(state.tool)?.receive(state),\n connection(next) {\n connection = next\n for (const handle of handles.values()) handle.connection()\n touch()\n },\n })\n }\n\n const studio: Studio = {\n definitions: tools,\n tools: [...handles.values()],\n tool<TConfig extends object>(definition: ToolDefinition<TConfig>) {\n const handle = handles.get(definition.id)\n if (!handle) throw new Error(`[studio] tool \"${definition.id}\" was not passed to createStudio`)\n return handle as unknown as ToolHandle<TConfig>\n },\n get connection() {\n return connection\n },\n get version() {\n return version\n },\n subscribe(listener) {\n studioListeners.add(listener)\n return () => void studioListeners.delete(listener)\n },\n close() {\n bridge?.close()\n for (const handle of handles.values()) handle.close()\n studioListeners.clear()\n if (typeof window !== 'undefined') window.removeEventListener?.('message', onMessage)\n if (instances.get(instanceKey) === studio) instances.delete(instanceKey)\n },\n }\n if (typeof window !== 'undefined') {\n instances.get(instanceKey)?.close()\n instances.set(instanceKey, studio)\n }\n return studio\n}\n\nfunction fail(result: Result<unknown>) {\n if (!result.ok) throw new Error(result.message ?? result.error)\n}\n","export type Change = { path: string[]; before: unknown; after: unknown }\n\n/** Every leaf that differs between two configs of the same shape. Arrays count as leaves. */\nexport function diff(before: unknown, after: unknown, path: string[] = []): Change[] {\n const nested = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n if (nested(before) && nested(after)) {\n const keys = new Set([...Object.keys(before), ...Object.keys(after)])\n return [...keys].flatMap((key) => diff(before[key], after[key], [...path, key]))\n }\n return JSON.stringify(before) === JSON.stringify(after) ? [] : [{ path, before, after }]\n}\n\n/** Dotted paths of every leaf that differs between two configs of the same shape. */\nexport function changedPaths(before: unknown, after: unknown): string[] {\n return diff(before, after).map(({ path }) => path.join('.'))\n}\n","import type { Op, Operations, ServerMessage, ToolState } from '../core/protocol'\nimport { error, type Result } from '../core/result'\n\nexport type Connection = { phase: 'local' } | { phase: 'connecting' } | { phase: 'connected' } | { phase: 'offline' }\n\ntype Pending = (result: Result<unknown>) => void\n\n/** A reconnecting WebSocket to the Studio runtime with request/response correlation. */\nexport function connectBridge(\n url: string,\n handlers: { state: (state: ToolState) => void; connection: (connection: Connection) => void },\n) {\n let socket: WebSocket | null = null\n let nextId = 0\n let retry = 0\n let timer: ReturnType<typeof setTimeout> | undefined\n let closed = false\n const pending = new Map<number, Pending>()\n\n const open = () => {\n handlers.connection({ phase: 'connecting' })\n const ws = new WebSocket(url)\n socket = ws\n ws.onopen = () => {\n retry = 0\n handlers.connection({ phase: 'connected' })\n }\n ws.onmessage = (event) => {\n const message = JSON.parse(String(event.data)) as ServerMessage\n if (message.type === 'state') return handlers.state(message.state)\n pending.get(message.id)?.(message.result)\n pending.delete(message.id)\n }\n ws.onclose = () => {\n socket = null\n for (const resolve of pending.values()) resolve(error('runtime_unavailable'))\n pending.clear()\n if (closed) return\n handlers.connection({ phase: 'offline' })\n timer = setTimeout(open, Math.min(500 * 2 ** retry++, 5000))\n }\n }\n open()\n\n return {\n request<TOp extends Op>(op: TOp, params: Operations[TOp]['params']): Promise<Result<Operations[TOp]['result']>> {\n if (socket?.readyState !== WebSocket.OPEN) return Promise.resolve(error('runtime_unavailable'))\n const id = nextId++\n socket.send(JSON.stringify({ id, op, params }))\n return new Promise((resolve) => pending.set(id, resolve as Pending))\n },\n close() {\n closed = true\n clearTimeout(timer)\n socket?.close()\n },\n }\n}\n\nexport type BridgeClient = ReturnType<typeof connectBridge>\n","import type { ToolDefinition } from '../core/tool'\nimport { validateConfig } from '../core/validate'\n\ntype Snapshot = { type: 'config'; clock: number; sender: string; value: unknown }\n\n/** Ephemeral config sharing between same-origin pages, including Studio's preview iframe. */\nexport function connectBrowserSync<T extends object>(\n definition: ToolDefinition<T>,\n runtime: string | false | undefined,\n handlers: { enabled(): boolean; receive(value: T): void },\n) {\n // Also exclude SSR and Node environments that expose their own BroadcastChannel implementation.\n if (typeof window === 'undefined' || !window.location?.origin || !window.BroadcastChannel) return null\n\n let channel: BroadcastChannel\n try {\n channel = new window.BroadcastChannel(\n JSON.stringify(['joyco-studio:config', runtime || null, definition.id, definition.file]),\n )\n } catch {\n return null\n }\n const sender = crypto.getRandomValues(new Uint32Array(4)).join('-')\n let clock = 0\n let latest: Snapshot | undefined\n let closed = false\n\n channel.onmessage = ({ data }) => {\n if (closed || !data || typeof data !== 'object') return\n if (data.type === 'request') {\n if (latest) channel.postMessage(latest)\n return\n }\n if (\n data.type !== 'config' ||\n !Number.isSafeInteger(data.clock) ||\n data.clock < 1 ||\n typeof data.sender !== 'string'\n )\n return\n clock = Math.max(clock, data.clock)\n if (!handlers.enabled()) return\n // A stable tie-break keeps simultaneous edits and multiple snapshot replies from diverging.\n if (latest && (data.clock < latest.clock || (data.clock === latest.clock && data.sender <= latest.sender))) return\n const result = validateConfig(definition, data.value)\n if (!result.ok) return\n latest = { type: 'config', clock: data.clock, sender: data.sender, value: result.data }\n handlers.receive(result.data)\n }\n // A newly mounted/reloaded preview asks existing peers for their current draft.\n channel.postMessage({ type: 'request' })\n\n return {\n publish(value: T) {\n if (closed) return\n latest = { type: 'config', clock: ++clock, sender, value: structuredClone(value) }\n channel.postMessage(latest)\n },\n close() {\n closed = true\n channel.onmessage = null\n channel.close()\n },\n }\n}\n","import { diff, type Change } from '../core/diff'\n\ntype Entry = { changes: Change[]; key: string; at: number }\n\nconst LIMIT = 100\n/** Edits to the same leaves this close together (a slider drag) undo as one step. */\nconst MERGE_MS = 500\n\n/**\n * Undo/redo for one page's edits. Entries hold only the leaves an edit changed, so stepping back\n * never reverts what another page, the runtime, or an agent changed in between.\n */\nexport function createHistory() {\n const past: Entry[] = []\n let future: Entry[] = []\n /** The newest entry while later edits to the same leaves may still extend it. */\n let open: Entry | null = null\n\n const step = (from: Entry[], to: Entry[], side: 'before' | 'after') => {\n const entry = from.pop()\n if (!entry) return null\n to.push(entry)\n open = null\n return entry.changes.map((change) => ({ path: change.path, value: change[side] }))\n }\n\n return {\n get canUndo() {\n return past.length > 0\n },\n get canRedo() {\n return future.length > 0\n },\n /** Record the edit between two snapshots. `merge: false` keeps it a step of its own (e.g. Discard). */\n record(before: unknown, after: unknown, { merge = true } = {}) {\n // Cloned so later in-place edits (e.g. to an array leaf) cannot rewrite history.\n const changes = structuredClone(diff(before, after))\n if (!changes.length) return\n future = []\n const key = JSON.stringify(changes.map(({ path }) => path))\n const now = Date.now()\n if (merge && open && open.key === key && now - open.at < MERGE_MS) {\n open.changes = open.changes.map((change, i) => ({ ...change, after: changes[i]!.after }))\n open.at = now\n // Dragged back to where it started: nothing left to undo.\n if (open.changes.every((change) => JSON.stringify(change.before) === JSON.stringify(change.after))) {\n past.pop()\n open = null\n }\n return\n }\n const entry = { changes, key, at: now }\n past.push(entry)\n if (past.length > LIMIT) past.shift()\n open = merge ? entry : null\n },\n /** The leaves to write back, or null when there is nothing to undo. */\n undo: () => step(past, future, 'before'),\n redo: () => step(future, past, 'after'),\n }\n}\n\n/** Write `value` at `path` in place; undefined removes the key (it did not exist before the edit). */\nexport function writePath(target: Record<string, unknown>, path: string[], value: unknown) {\n const key = path.at(-1)!\n let parent = target\n for (const segment of path.slice(0, -1)) {\n const next = parent[segment]\n parent = (typeof next === 'object' && next !== null ? next : (parent[segment] = {})) as Record<string, unknown>\n }\n if (value === undefined) delete parent[key]\n else parent[key] = structuredClone(value)\n}\n","/**\n * A deep proxy that reports every write, so plain `property(config, 'key')`\n * bindings from Xyz feed Studio without the tool author wiring callbacks.\n */\nexport function live<T extends object>(target: T, onWrite: () => void): T {\n const proxies = new WeakMap<object, object>()\n const wrap = <O extends object>(object: O): O => {\n let proxy = proxies.get(object)\n if (!proxy) {\n proxy = new Proxy(object, {\n get(target, key, receiver) {\n const value = Reflect.get(target, key, receiver)\n return typeof value === 'object' && value !== null ? wrap(value) : value\n },\n set(target, key, value, receiver) {\n const changed = Reflect.get(target, key, receiver) !== value\n const ok = Reflect.set(target, key, value, receiver)\n if (changed) onWrite()\n return ok\n },\n })\n proxies.set(object, proxy)\n }\n return proxy as O\n }\n return wrap(target)\n}\n\n/**\n * Make `target` equal `source` in place, keeping nested object identities (and every binding to them) intact.\n * Keys `source` lacks are removed.\n */\nexport function assignDeep(target: Record<string, unknown>, source: Record<string, unknown>) {\n for (const key of Object.keys(target)) if (!(key in source)) delete target[key]\n for (const [key, value] of Object.entries(source)) {\n const current = target[key]\n const nested = (v: unknown) => typeof v === 'object' && v !== null && !Array.isArray(v)\n if (nested(current) && nested(value))\n assignDeep(current as Record<string, unknown>, value as Record<string, unknown>)\n else target[key] = structuredClone(value)\n }\n}\n"],"mappings":"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","names":["target"]}
|