made-refine 0.2.20 → 0.3.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/dist/index.js CHANGED
@@ -87,7 +87,7 @@ var React8 = __toESM(require("react"));
87
87
  var React = __toESM(require("react"));
88
88
 
89
89
  // dist/styles.css
90
- var styles_default = '/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--leading-relaxed:1.625;--radius-sm:calc(.5rem - 4px);--radius-md:calc(.5rem - 2px);--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-border:#e6e6e6;--color-ring:#262626;--color-background:#fff;--color-foreground:#171717;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary-foreground:#171717;--color-destructive:#ef4444;--color-destructive-foreground:#fafafa;--color-muted:#f2f2f2;--color-muted-foreground:#737373;--color-popover-foreground:#171717}}@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,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-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{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root,:host{color-scheme:light;color:var(--color-foreground)}@media (prefers-color-scheme:dark){:root,:host(:not([data-theme])),:host([data-theme=system]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}}:host([data-theme=dark]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:var(--color-background);--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;border-color:var(--color-border)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.top-1\\/2{top:50%}.left-1\\.5{left:calc(var(--spacing)*1.5)}.left-1\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.z-\\[99990\\]{z-index:99990}.z-\\[99991\\]{z-index:99991}.z-\\[99998\\]{z-index:99998}.z-\\[99999\\]{z-index:99999}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-4{margin:calc(var(--spacing)*4)}.mx-0\\.5{margin-inline:calc(var(--spacing)*.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.my-0\\.5{margin-block:calc(var(--spacing)*.5)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2\\.5{margin-top:calc(var(--spacing)*2.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0{margin-left:calc(var(--spacing)*0)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.size-1{width:calc(var(--spacing)*1);height:calc(var(--spacing)*1)}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-full{width:100%;height:100%}.h-0\\.5{height:calc(var(--spacing)*.5)}.h-2{height:calc(var(--spacing)*2)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.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-11{height:calc(var(--spacing)*11)}.h-\\[150px\\]{height:150px}.h-auto{height:auto}.h-fit{height:fit-content}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\\[240px\\]{max-height:240px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\\[18px\\]{min-height:18px}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-14{width:calc(var(--spacing)*14)}.w-\\[1\\.5px\\]{width:1.5px}.w-\\[60px\\]{width:60px}.w-\\[68px\\]{width:68px}.w-\\[180px\\]{width:180px}.w-\\[200px\\]{width:200px}.w-\\[240px\\]{width:240px}.w-\\[260px\\]{width:260px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\\[18px\\]{min-width:18px}.min-w-\\[20px\\]{min-width:20px}.min-w-\\[100px\\]{min-width:100px}.min-w-\\[120px\\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-\\(--transform-origin\\){transform-origin:var(--transform-origin)}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);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)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-crosshair{cursor:crosshair}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.\\[appearance\\:textfield\\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\\[0fr\\]{grid-template-columns:0fr}.grid-cols-\\[1fr\\]{grid-template-columns:1fr}.grid-rows-\\[0fr\\]{grid-template-rows:0fr}.grid-rows-\\[1fr\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-evenly{justify-content:space-evenly}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-\\[2px\\]{gap:2px}.gap-\\[4px\\]{gap:4px}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\\[6px\\]{border-radius:6px}.rounded-\\[8px\\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-tl{border-top-left-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-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-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.\\[border-top-style\\:solid\\]{border-top-style:solid}.\\[border-right-style\\:dashed\\]{border-right-style:dashed}.\\[border-bottom-style\\:dashed\\]{border-bottom-style:dashed}.\\[border-bottom-style\\:dotted\\]{border-bottom-style:dotted}.\\[border-bottom-style\\:solid\\]{border-bottom-style:solid}.\\[border-left-style\\:double\\]{border-left-style:double}.\\[border-left-style\\:solid\\]{border-left-style:solid}.border-border{border-color:var(--color-border)}.border-border\\/30{border-color:#e6e6e64d}@supports (color:color-mix(in lab, red, red)){.border-border\\/30{border-color:color-mix(in oklab,var(--color-border)30%,transparent)}}.border-border\\/50{border-color:#e6e6e680}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--color-border)50%,transparent)}}.border-foreground\\/10{border-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/10{border-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-\\[canvas\\]{background-color:canvas}.bg-background{background-color:var(--color-background)}.bg-background\\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab, red, red)){.bg-background\\/85{background-color:color-mix(in oklab,var(--color-background)85%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--color-border)}.bg-destructive{background-color:var(--color-destructive)}.bg-foreground{background-color:var(--color-foreground)}.bg-foreground\\/25{background-color:#17171740}@supports (color:color-mix(in lab, red, red)){.bg-foreground\\/25{background-color:color-mix(in oklab,var(--color-foreground)25%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\\/30{background-color:#7373734d}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/30{background-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-transparent{background-color:#0000}.fill-border{fill:var(--color-border)}.p-0{padding:calc(var(--spacing)*0)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0{padding-block:calc(var(--spacing)*0)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-3\\.5{padding-block:calc(var(--spacing)*3.5)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2\\.5{padding-top:calc(var(--spacing)*2.5)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pt-\\[13px\\]{padding-top:13px}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-1\\.5{padding-right:calc(var(--spacing)*1.5)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-1\\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.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-\\[7px\\]{font-size:7px}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.leading-\\[18px\\]{--tw-leading:18px;line-height:18px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-extralight{--tw-font-weight:var(--font-weight-extralight);font-weight:var(--font-weight-extralight)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.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)}.font-thin{--tw-font-weight:var(--font-weight-thin);font-weight:var(--font-weight-thin)}.\\[overflow-wrap\\:anywhere\\]{overflow-wrap:anywhere}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-background{color:var(--color-background)}.text-blue-500{color:var(--color-blue-500)}.text-destructive-foreground{color:var(--color-destructive-foreground)}.text-foreground{color:var(--color-foreground)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-popover-foreground{color:var(--color-popover-foreground)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xs{--tw-shadow:0 1px 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-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.3\\)\\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0000004d);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_4px_6px_-1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 6px -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-\\[inset_0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:inset 0 0 0 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-inner{--tw-shadow:inset 0 2px 4px 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-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-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.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)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-white{--tw-ring-color:var(--color-white)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.outline-border{outline-color:var(--color-border)}.outline-foreground\\/10{outline-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.outline-foreground\\/10{outline-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.outline-red-500\\/70{outline-color:#fb2c36b3}@supports (color:color-mix(in lab, red, red)){.outline-red-500\\/70{outline-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.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\\,background-color\\]{transition-property:color,background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[opacity\\,background-color\\,color\\]{transition-property:opacity,background-color,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[transform\\,scale\\,opacity\\]{transition-property:transform,scale,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.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-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.\\[-ms-overflow-style\\:none\\]{-ms-overflow-style:none}.\\[scrollbar-width\\:none\\]{scrollbar-width:none}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}@media (hover:hover){.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\\/pin\\:inline:is(:where(.group\\/pin):hover *){display:inline}}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--color-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.placeholder\\:text-red-400::placeholder{color:var(--color-red-400)}.focus-within\\:ring-1:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--color-ring)}.focus-within\\:outline-none:focus-within{--tw-outline-style:none;outline-style:none}.focus-within\\:ring-inset:focus-within{--tw-ring-inset:inset}@media (hover:hover){.hover\\:scale-\\[1\\.67\\]:hover{scale:1.67}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive\\/90:hover{background-color:#ef4444e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--color-destructive)90%,transparent)}}.hover\\:bg-foreground\\/80:hover{background-color:#171717cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-foreground\\/80:hover{background-color:color-mix(in oklab,var(--color-foreground)80%,transparent)}}.hover\\:bg-muted:hover{background-color:var(--color-muted)}.hover\\:bg-muted-foreground\\/10:hover{background-color:#7373731a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/10:hover{background-color:color-mix(in oklab,var(--color-muted-foreground)10%,transparent)}}.hover\\:bg-muted\\/50:hover{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/50:hover{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.hover\\:bg-muted\\/80:hover{background-color:#f2f2f2cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/80:hover{background-color:color-mix(in oklab,var(--color-muted)80%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\\:text-foreground:hover{color:var(--color-foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:shadow-lg:hover{--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)}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-inset:focus-visible{--tw-ring-inset:inset}.active\\:cursor-grabbing:active{cursor:grabbing}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.data-ending-style\\:scale-90[data-ending-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-ending-style\\:opacity-0[data-ending-style]{opacity:0}.data-instant\\:transition-none[data-instant]{transition-property:none}.data-starting-style\\:scale-90[data-starting-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-starting-style\\:opacity-0[data-starting-style]{opacity:0}.data-\\[highlighted\\]\\:bg-muted[data-highlighted]{background-color:var(--color-muted)}.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.data-\\[highlighted\\]\\:text-foreground[data-highlighted]{color:var(--color-foreground)}@media (prefers-color-scheme:dark){.dark\\:shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\\:-outline-offset-1{outline-offset:calc(1px*-1)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-3\\.5 svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\:\\:-webkit-inner-spin-button\\]\\:appearance-none::-webkit-inner-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-outer-spin-button\\]\\:appearance-none::-webkit-outer-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-scrollbar\\]\\:hidden::-webkit-scrollbar{display:none}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none;animation:none}}.lucide{stroke-width:1px}@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))}}@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))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes pulse{50%{opacity:.5}}';
90
+ var styles_default = '/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--leading-relaxed:1.625;--radius-sm:calc(.5rem - 4px);--radius-md:calc(.5rem - 2px);--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-border:#e6e6e6;--color-ring:#262626;--color-background:#fff;--color-foreground:#171717;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary-foreground:#171717;--color-destructive:#ef4444;--color-destructive-foreground:#fafafa;--color-muted:#f2f2f2;--color-muted-foreground:#737373;--color-popover-foreground:#171717}}@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,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-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{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root,:host{color-scheme:light;color:var(--color-foreground)}@media (prefers-color-scheme:dark){:root,:host(:not([data-theme])),:host([data-theme=system]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}}:host([data-theme=dark]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:var(--color-background);--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;border-color:var(--color-border)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.top-1\\/2{top:50%}.left-1\\.5{left:calc(var(--spacing)*1.5)}.left-1\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.isolate{isolation:isolate}.z-\\[99990\\]{z-index:99990}.z-\\[99991\\]{z-index:99991}.z-\\[99998\\]{z-index:99998}.z-\\[99999\\]{z-index:99999}.\\!container{width:100%!important}@media (min-width:40rem){.\\!container{max-width:40rem!important}}@media (min-width:48rem){.\\!container{max-width:48rem!important}}@media (min-width:64rem){.\\!container{max-width:64rem!important}}@media (min-width:80rem){.\\!container{max-width:80rem!important}}@media (min-width:96rem){.\\!container{max-width:96rem!important}}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-4{margin:calc(var(--spacing)*4)}.mx-0\\.5{margin-inline:calc(var(--spacing)*.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.my-0\\.5{margin-block:calc(var(--spacing)*.5)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2\\.5{margin-top:calc(var(--spacing)*2.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0{margin-left:calc(var(--spacing)*0)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.table{display:table}.size-1{width:calc(var(--spacing)*1);height:calc(var(--spacing)*1)}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-full{width:100%;height:100%}.h-0\\.5{height:calc(var(--spacing)*.5)}.h-2{height:calc(var(--spacing)*2)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.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-11{height:calc(var(--spacing)*11)}.h-\\[150px\\]{height:150px}.h-auto{height:auto}.h-fit{height:fit-content}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\\[240px\\]{max-height:240px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\\[18px\\]{min-height:18px}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-14{width:calc(var(--spacing)*14)}.w-\\[1\\.5px\\]{width:1.5px}.w-\\[60px\\]{width:60px}.w-\\[68px\\]{width:68px}.w-\\[180px\\]{width:180px}.w-\\[200px\\]{width:200px}.w-\\[240px\\]{width:240px}.w-\\[260px\\]{width:260px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\\[18px\\]{min-width:18px}.min-w-\\[20px\\]{min-width:20px}.min-w-\\[100px\\]{min-width:100px}.min-w-\\[120px\\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-\\(--transform-origin\\){transform-origin:var(--transform-origin)}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.rotate-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-pulse{animation:var(--animate-pulse)}.cursor-crosshair{cursor:crosshair}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.\\[appearance\\:textfield\\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\\[0fr\\]{grid-template-columns:0fr}.grid-cols-\\[1fr\\]{grid-template-columns:1fr}.grid-rows-\\[0fr\\]{grid-template-rows:0fr}.grid-rows-\\[1fr\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-evenly{justify-content:space-evenly}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-\\[2px\\]{gap:2px}.gap-\\[4px\\]{gap:4px}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\\[6px\\]{border-radius:6px}.rounded-\\[8px\\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-tl{border-top-left-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-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-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.\\[border-top-style\\:solid\\]{border-top-style:solid}.\\[border-right-style\\:dashed\\]{border-right-style:dashed}.\\[border-bottom-style\\:dashed\\]{border-bottom-style:dashed}.\\[border-bottom-style\\:dotted\\]{border-bottom-style:dotted}.\\[border-bottom-style\\:solid\\]{border-bottom-style:solid}.\\[border-left-style\\:double\\]{border-left-style:double}.\\[border-left-style\\:solid\\]{border-left-style:solid}.border-border{border-color:var(--color-border)}.border-border\\/30{border-color:#e6e6e64d}@supports (color:color-mix(in lab, red, red)){.border-border\\/30{border-color:color-mix(in oklab,var(--color-border)30%,transparent)}}.border-border\\/50{border-color:#e6e6e680}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--color-border)50%,transparent)}}.border-foreground\\/10{border-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/10{border-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-\\[canvas\\]{background-color:canvas}.bg-background{background-color:var(--color-background)}.bg-background\\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab, red, red)){.bg-background\\/85{background-color:color-mix(in oklab,var(--color-background)85%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--color-border)}.bg-destructive{background-color:var(--color-destructive)}.bg-foreground{background-color:var(--color-foreground)}.bg-foreground\\/25{background-color:#17171740}@supports (color:color-mix(in lab, red, red)){.bg-foreground\\/25{background-color:color-mix(in oklab,var(--color-foreground)25%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\\/30{background-color:#7373734d}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/30{background-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-transparent{background-color:#0000}.fill-border{fill:var(--color-border)}.p-0{padding:calc(var(--spacing)*0)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0{padding-block:calc(var(--spacing)*0)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-3\\.5{padding-block:calc(var(--spacing)*3.5)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2\\.5{padding-top:calc(var(--spacing)*2.5)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pt-\\[13px\\]{padding-top:13px}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-1\\.5{padding-right:calc(var(--spacing)*1.5)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-1\\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.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-\\[7px\\]{font-size:7px}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.leading-\\[18px\\]{--tw-leading:18px;line-height:18px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-extralight{--tw-font-weight:var(--font-weight-extralight);font-weight:var(--font-weight-extralight)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.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)}.font-thin{--tw-font-weight:var(--font-weight-thin);font-weight:var(--font-weight-thin)}.\\[overflow-wrap\\:anywhere\\]{overflow-wrap:anywhere}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-background{color:var(--color-background)}.text-blue-500{color:var(--color-blue-500)}.text-destructive-foreground{color:var(--color-destructive-foreground)}.text-foreground{color:var(--color-foreground)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-popover-foreground{color:var(--color-popover-foreground)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xs{--tw-shadow:0 1px 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-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.3\\)\\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0000004d);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_4px_6px_-1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 6px -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-\\[inset_0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:inset 0 0 0 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-inner{--tw-shadow:inset 0 2px 4px 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-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-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.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)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-white{--tw-ring-color:var(--color-white)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.outline-border{outline-color:var(--color-border)}.outline-foreground\\/10{outline-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.outline-foreground\\/10{outline-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.outline-red-500\\/70{outline-color:#fb2c36b3}@supports (color:color-mix(in lab, red, red)){.outline-red-500\\/70{outline-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.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\\,background-color\\]{transition-property:color,background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[opacity\\,background-color\\,color\\]{transition-property:opacity,background-color,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[transform\\,scale\\,opacity\\]{transition-property:transform,scale,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.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-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.\\[-ms-overflow-style\\:none\\]{-ms-overflow-style:none}.\\[scrollbar-width\\:none\\]{scrollbar-width:none}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}@media (hover:hover){.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\\/pin\\:inline:is(:where(.group\\/pin):hover *){display:inline}}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--color-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.placeholder\\:text-red-400::placeholder{color:var(--color-red-400)}.focus-within\\:ring-1:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--color-ring)}.focus-within\\:outline-none:focus-within{--tw-outline-style:none;outline-style:none}.focus-within\\:ring-inset:focus-within{--tw-ring-inset:inset}@media (hover:hover){.hover\\:scale-\\[1\\.67\\]:hover{scale:1.67}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive\\/90:hover{background-color:#ef4444e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--color-destructive)90%,transparent)}}.hover\\:bg-foreground\\/80:hover{background-color:#171717cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-foreground\\/80:hover{background-color:color-mix(in oklab,var(--color-foreground)80%,transparent)}}.hover\\:bg-muted:hover{background-color:var(--color-muted)}.hover\\:bg-muted-foreground\\/10:hover{background-color:#7373731a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/10:hover{background-color:color-mix(in oklab,var(--color-muted-foreground)10%,transparent)}}.hover\\:bg-muted\\/50:hover{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/50:hover{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.hover\\:bg-muted\\/80:hover{background-color:#f2f2f2cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/80:hover{background-color:color-mix(in oklab,var(--color-muted)80%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\\:text-foreground:hover{color:var(--color-foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:shadow-lg:hover{--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)}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-inset:focus-visible{--tw-ring-inset:inset}.active\\:cursor-grabbing:active{cursor:grabbing}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.data-ending-style\\:scale-90[data-ending-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-ending-style\\:opacity-0[data-ending-style]{opacity:0}.data-instant\\:transition-none[data-instant]{transition-property:none}.data-starting-style\\:scale-90[data-starting-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-starting-style\\:opacity-0[data-starting-style]{opacity:0}.data-\\[highlighted\\]\\:bg-muted[data-highlighted]{background-color:var(--color-muted)}.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.data-\\[highlighted\\]\\:text-foreground[data-highlighted]{color:var(--color-foreground)}@media (prefers-color-scheme:dark){.dark\\:shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\\:-outline-offset-1{outline-offset:calc(1px*-1)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-3\\.5 svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\:\\:-webkit-inner-spin-button\\]\\:appearance-none::-webkit-inner-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-outer-spin-button\\]\\:appearance-none::-webkit-outer-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-scrollbar\\]\\:hidden::-webkit-scrollbar{display:none}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none;animation:none}}.lucide{stroke-width:1px}@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))}}@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))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes pulse{50%{opacity:.5}}';
91
91
 
92
92
  // src/portal-container.tsx
93
93
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -477,10 +477,30 @@ function getSourceFromFiber(fiber) {
477
477
  if (fromDebugStack?.fileName) return fromDebugStack;
478
478
  return null;
479
479
  }
480
+ var REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref");
481
+ var REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo");
482
+ function resolveComponentName(type) {
483
+ let current = type;
484
+ for (let depth = 0; depth < 4 && current != null; depth++) {
485
+ const name = current.displayName || (typeof current === "function" ? current.name : void 0);
486
+ if (name) return name;
487
+ if (typeof current !== "object") return null;
488
+ if (current.$$typeof === REACT_MEMO_TYPE) {
489
+ current = current.type;
490
+ continue;
491
+ }
492
+ if (current.$$typeof === REACT_FORWARD_REF_TYPE) {
493
+ current = current.render;
494
+ continue;
495
+ }
496
+ return null;
497
+ }
498
+ return null;
499
+ }
480
500
  function buildFrame(fiber) {
481
501
  const type = fiber?.type;
482
502
  if (typeof type !== "function" && typeof type !== "object") return null;
483
- const name = type?.displayName || type?.name || null;
503
+ const name = resolveComponentName(type);
484
504
  if (!name || name === "Fragment") return null;
485
505
  const frame = { name };
486
506
  const source = getSourceFromFiber(fiber);
@@ -552,14 +572,7 @@ function getReactComponentInfo(element) {
552
572
  }
553
573
  return { ...getRenderStack(fiber), elementSourceFile };
554
574
  }
555
- var EXCLUDED_PROP_KEYS = /* @__PURE__ */ new Set([
556
- "className",
557
- "style",
558
- "children",
559
- "ref",
560
- "key",
561
- "render"
562
- ]);
575
+ var EXCLUDED_PROP_KEYS = /* @__PURE__ */ new Set(["className", "style", "children", "ref", "key", "render"]);
563
576
  function serializePropValue(value) {
564
577
  if (typeof value === "function") return "[function]";
565
578
  if (typeof value === "symbol") return void 0;
@@ -670,19 +683,7 @@ function classifyComponentFiber(fiber, frames, elementSourceFile) {
670
683
  return { isComponentPrimitive: false };
671
684
  }
672
685
 
673
- // src/utils.ts
674
- function clamp(value, min, max) {
675
- if (!Number.isFinite(value)) return min;
676
- if (max < min) return min;
677
- return Math.max(min, Math.min(max, value));
678
- }
679
- function isInputFocused() {
680
- let active = document.activeElement;
681
- while (active?.shadowRoot?.activeElement) {
682
- active = active.shadowRoot.activeElement;
683
- }
684
- return active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
685
- }
686
+ // src/utils/computed-styles.ts
686
687
  function getComputedStyles(element) {
687
688
  const computed = window.getComputedStyle(element);
688
689
  return {
@@ -791,6 +792,255 @@ function getOriginalInlineStyles(element) {
791
792
  }
792
793
  return styles;
793
794
  }
795
+ function getComputedTypography(element) {
796
+ const computed = window.getComputedStyle(element);
797
+ let textVerticalAlign = "flex-start";
798
+ if (computed.display === "flex" || computed.display === "inline-flex") {
799
+ const alignItems = computed.alignItems;
800
+ if (alignItems === "center") textVerticalAlign = "center";
801
+ else if (alignItems === "flex-end" || alignItems === "end") textVerticalAlign = "flex-end";
802
+ }
803
+ const lineHeight = computed.lineHeight === "normal" ? {
804
+ numericValue: parseFloat(computed.fontSize) * 1.2,
805
+ unit: "px",
806
+ raw: `${Math.round(parseFloat(computed.fontSize) * 1.2)}px`
807
+ } : parsePropertyValue(computed.lineHeight);
808
+ const fontSize = parseFloat(computed.fontSize);
809
+ let letterSpacing;
810
+ if (computed.letterSpacing === "normal") {
811
+ letterSpacing = { numericValue: 0, unit: "em", raw: "0em" };
812
+ } else {
813
+ const parsed = parsePropertyValue(computed.letterSpacing);
814
+ if (parsed.unit === "px" && fontSize > 0) {
815
+ const emValue = Math.round(parsed.numericValue / fontSize * 100) / 100;
816
+ letterSpacing = { numericValue: emValue, unit: "em", raw: `${emValue}em` };
817
+ } else {
818
+ letterSpacing = parsed;
819
+ }
820
+ }
821
+ return {
822
+ fontFamily: computed.fontFamily,
823
+ fontWeight: computed.fontWeight,
824
+ fontSize: parsePropertyValue(computed.fontSize),
825
+ lineHeight,
826
+ letterSpacing,
827
+ textAlign: computed.textAlign,
828
+ textVerticalAlign
829
+ };
830
+ }
831
+ function getComputedSizing(element) {
832
+ return {
833
+ width: getSizingValue(element, "width"),
834
+ height: getSizingValue(element, "height")
835
+ };
836
+ }
837
+ var TEXT_ELEMENT_TAGS = /* @__PURE__ */ new Set([
838
+ "p",
839
+ "h1",
840
+ "h2",
841
+ "h3",
842
+ "h4",
843
+ "h5",
844
+ "h6",
845
+ "span",
846
+ "label",
847
+ "a",
848
+ "strong",
849
+ "em",
850
+ "small",
851
+ "blockquote",
852
+ "li",
853
+ "td",
854
+ "th",
855
+ "caption",
856
+ "figcaption",
857
+ "legend",
858
+ "dt",
859
+ "dd",
860
+ "abbr",
861
+ "cite",
862
+ "code",
863
+ "pre"
864
+ ]);
865
+ function hasDirectNonWhitespaceText(element) {
866
+ return Array.from(element.childNodes).some(
867
+ (node) => node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim())
868
+ );
869
+ }
870
+ var TRANSPARENT_COLOR = { hex: "000000", alpha: 0, raw: "transparent" };
871
+ function isVisibleBorderSide(side) {
872
+ return side.style !== "none" && side.style !== "hidden" && parseFloat(side.width) > 0;
873
+ }
874
+ function hasVisibleOutline(computed) {
875
+ return computed.outlineStyle !== "none" && parseFloat(computed.outlineWidth) > 0;
876
+ }
877
+ function parseVisibleColor(value, fallbackCurrentColor) {
878
+ const raw = value.trim();
879
+ const lowered = raw.toLowerCase();
880
+ if (!raw || lowered === "none" || lowered === "transparent") {
881
+ return null;
882
+ }
883
+ const resolved = /^currentcolor$/i.test(raw) ? fallbackCurrentColor ?? raw : raw;
884
+ const parsed = parseColorValue(resolved);
885
+ if (parsed.alpha <= 0) {
886
+ return null;
887
+ }
888
+ return parsed;
889
+ }
890
+ function addUniqueColor(colors, color) {
891
+ if (!color) return;
892
+ colors.set(`${color.hex}:${color.alpha}`, color);
893
+ }
894
+ function isTextRenderingFormControl(element) {
895
+ if (element instanceof HTMLTextAreaElement) return true;
896
+ if (element instanceof HTMLSelectElement) return true;
897
+ if (element instanceof HTMLButtonElement) return true;
898
+ if (element instanceof HTMLInputElement) {
899
+ const textlessInputTypes = /* @__PURE__ */ new Set([
900
+ "hidden",
901
+ "checkbox",
902
+ "radio",
903
+ "range",
904
+ "color",
905
+ "file",
906
+ "image"
907
+ ]);
908
+ return !textlessInputTypes.has(element.type.toLowerCase());
909
+ }
910
+ return false;
911
+ }
912
+ function hasRenderableTextNode(element) {
913
+ if (element.isContentEditable) return true;
914
+ if (isTextRenderingFormControl(element)) return true;
915
+ if (!element.textContent?.trim()) return false;
916
+ if (hasDirectNonWhitespaceText(element)) return true;
917
+ const tagName = element.tagName.toLowerCase();
918
+ return TEXT_ELEMENT_TAGS.has(tagName) || element.children.length === 0;
919
+ }
920
+ function getComputedBoxShadow(element) {
921
+ const computed = window.getComputedStyle(element);
922
+ const value = computed.boxShadow.trim();
923
+ return value || "none";
924
+ }
925
+ function getComputedColorStyles(element) {
926
+ const computed = window.getComputedStyle(element);
927
+ const borderSides = [
928
+ {
929
+ style: computed.borderTopStyle,
930
+ width: computed.borderTopWidth,
931
+ color: computed.borderTopColor
932
+ },
933
+ {
934
+ style: computed.borderRightStyle,
935
+ width: computed.borderRightWidth,
936
+ color: computed.borderRightColor
937
+ },
938
+ {
939
+ style: computed.borderBottomStyle,
940
+ width: computed.borderBottomWidth,
941
+ color: computed.borderBottomColor
942
+ },
943
+ {
944
+ style: computed.borderLeftStyle,
945
+ width: computed.borderLeftWidth,
946
+ color: computed.borderLeftColor
947
+ }
948
+ ];
949
+ const visibleBorderSide = borderSides.find((side) => isVisibleBorderSide(side));
950
+ const hasBorder = Boolean(visibleBorderSide);
951
+ const hasOutline = hasVisibleOutline(computed);
952
+ return {
953
+ backgroundColor: parseColorValue(computed.backgroundColor),
954
+ color: parseColorValue(computed.color),
955
+ borderColor: hasBorder && visibleBorderSide ? parseColorValue(visibleBorderSide.color) : TRANSPARENT_COLOR,
956
+ outlineColor: hasOutline ? parseColorValue(computed.outlineColor) : TRANSPARENT_COLOR
957
+ };
958
+ }
959
+ function getSelectionColors(element) {
960
+ const uniqueColors = /* @__PURE__ */ new Map();
961
+ const queue = [element];
962
+ for (let index = 0; index < queue.length; index++) {
963
+ const node = queue[index];
964
+ const computed = window.getComputedStyle(node);
965
+ if (computed.display === "none") {
966
+ continue;
967
+ }
968
+ const isVisibilityHidden = computed.visibility === "hidden" || computed.visibility === "collapse";
969
+ const currentTextColor = computed.color;
970
+ if (!isVisibilityHidden) {
971
+ addUniqueColor(uniqueColors, parseVisibleColor(computed.backgroundColor));
972
+ if (node instanceof HTMLElement && hasRenderableTextNode(node)) {
973
+ addUniqueColor(uniqueColors, parseVisibleColor(currentTextColor));
974
+ }
975
+ const borderSides = [
976
+ {
977
+ style: computed.borderTopStyle,
978
+ width: computed.borderTopWidth,
979
+ color: computed.borderTopColor
980
+ },
981
+ {
982
+ style: computed.borderRightStyle,
983
+ width: computed.borderRightWidth,
984
+ color: computed.borderRightColor
985
+ },
986
+ {
987
+ style: computed.borderBottomStyle,
988
+ width: computed.borderBottomWidth,
989
+ color: computed.borderBottomColor
990
+ },
991
+ {
992
+ style: computed.borderLeftStyle,
993
+ width: computed.borderLeftWidth,
994
+ color: computed.borderLeftColor
995
+ }
996
+ ];
997
+ for (const side of borderSides) {
998
+ if (!isVisibleBorderSide(side)) continue;
999
+ addUniqueColor(uniqueColors, parseVisibleColor(side.color, currentTextColor));
1000
+ }
1001
+ if (hasVisibleOutline(computed)) {
1002
+ addUniqueColor(uniqueColors, parseVisibleColor(computed.outlineColor, currentTextColor));
1003
+ }
1004
+ if (node instanceof SVGElement) {
1005
+ const fillColor = parseVisibleColor(computed.getPropertyValue("fill"), currentTextColor) ?? parseVisibleColor(node.getAttribute("fill") ?? "", currentTextColor);
1006
+ const strokeColor = parseVisibleColor(computed.getPropertyValue("stroke"), currentTextColor) ?? parseVisibleColor(node.getAttribute("stroke") ?? "", currentTextColor);
1007
+ addUniqueColor(uniqueColors, fillColor);
1008
+ addUniqueColor(uniqueColors, strokeColor);
1009
+ }
1010
+ }
1011
+ for (const child of node.children) {
1012
+ queue.push(child);
1013
+ }
1014
+ }
1015
+ return Array.from(uniqueColors.values());
1016
+ }
1017
+ function getAllComputedStyles(element) {
1018
+ const { spacing, borderRadius, flex } = getComputedStyles(element);
1019
+ return {
1020
+ spacing,
1021
+ borderRadius,
1022
+ border: getComputedBorderStyles(element),
1023
+ flex,
1024
+ sizing: getComputedSizing(element),
1025
+ color: getComputedColorStyles(element),
1026
+ boxShadow: getComputedBoxShadow(element),
1027
+ typography: getComputedTypography(element)
1028
+ };
1029
+ }
1030
+
1031
+ // src/utils.ts
1032
+ function clamp(value, min, max) {
1033
+ if (!Number.isFinite(value)) return min;
1034
+ if (max < min) return min;
1035
+ return Math.max(min, Math.min(max, value));
1036
+ }
1037
+ function isInputFocused() {
1038
+ let active = document.activeElement;
1039
+ while (active?.shadowRoot?.activeElement) {
1040
+ active = active.shadowRoot.activeElement;
1041
+ }
1042
+ return active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
1043
+ }
794
1044
  var spacingScale = { 0: "0", 1: "px", 2: "0.5", 4: "1", 8: "2", 12: "3", 16: "4", 20: "5", 24: "6", 32: "8" };
795
1045
  var tailwindClassMap = {
796
1046
  padding: { prefix: "p", scale: spacingScale },
@@ -1117,7 +1367,7 @@ var typographyPropertyToCSSMap = {
1117
1367
  textAlign: "text-align",
1118
1368
  textVerticalAlign: "align-items"
1119
1369
  };
1120
- var TEXT_ELEMENT_TAGS = /* @__PURE__ */ new Set([
1370
+ var TEXT_ELEMENT_TAGS2 = /* @__PURE__ */ new Set([
1121
1371
  "p",
1122
1372
  "h1",
1123
1373
  "h2",
@@ -1145,55 +1395,23 @@ var TEXT_ELEMENT_TAGS = /* @__PURE__ */ new Set([
1145
1395
  "code",
1146
1396
  "pre"
1147
1397
  ]);
1148
- function hasDirectNonWhitespaceText(element) {
1398
+ function hasDirectNonWhitespaceText2(element) {
1149
1399
  return Array.from(element.childNodes).some(
1150
1400
  (node) => node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim())
1151
1401
  );
1152
1402
  }
1153
1403
  function isTextElement2(element) {
1154
1404
  const tagName = element.tagName.toLowerCase();
1155
- if (TEXT_ELEMENT_TAGS.has(tagName)) {
1156
- return true;
1157
- }
1158
- if (hasDirectNonWhitespaceText(element)) {
1159
- return true;
1160
- }
1161
- if (element.children.length === 0 && element.textContent?.trim()) {
1162
- return true;
1163
- }
1164
- return false;
1165
- }
1166
- function getComputedTypography(element) {
1167
- const computed = window.getComputedStyle(element);
1168
- let textVerticalAlign = "flex-start";
1169
- if (computed.display === "flex" || computed.display === "inline-flex") {
1170
- const alignItems = computed.alignItems;
1171
- if (alignItems === "center") textVerticalAlign = "center";
1172
- else if (alignItems === "flex-end" || alignItems === "end") textVerticalAlign = "flex-end";
1173
- }
1174
- const lineHeight = computed.lineHeight === "normal" ? { numericValue: parseFloat(computed.fontSize) * 1.2, unit: "px", raw: `${Math.round(parseFloat(computed.fontSize) * 1.2)}px` } : parsePropertyValue(computed.lineHeight);
1175
- const fontSize = parseFloat(computed.fontSize);
1176
- let letterSpacing;
1177
- if (computed.letterSpacing === "normal") {
1178
- letterSpacing = { numericValue: 0, unit: "em", raw: "0em" };
1179
- } else {
1180
- const parsed = parsePropertyValue(computed.letterSpacing);
1181
- if (parsed.unit === "px" && fontSize > 0) {
1182
- const emValue = Math.round(parsed.numericValue / fontSize * 100) / 100;
1183
- letterSpacing = { numericValue: emValue, unit: "em", raw: `${emValue}em` };
1184
- } else {
1185
- letterSpacing = parsed;
1186
- }
1187
- }
1188
- return {
1189
- fontFamily: computed.fontFamily,
1190
- fontWeight: computed.fontWeight,
1191
- fontSize: parsePropertyValue(computed.fontSize),
1192
- lineHeight,
1193
- letterSpacing,
1194
- textAlign: computed.textAlign,
1195
- textVerticalAlign
1196
- };
1405
+ if (TEXT_ELEMENT_TAGS2.has(tagName)) {
1406
+ return true;
1407
+ }
1408
+ if (hasDirectNonWhitespaceText2(element)) {
1409
+ return true;
1410
+ }
1411
+ if (element.children.length === 0 && element.textContent?.trim()) {
1412
+ return true;
1413
+ }
1414
+ return false;
1197
1415
  }
1198
1416
  function detectSizingMode(element, dimension) {
1199
1417
  const computed = window.getComputedStyle(element);
@@ -1242,12 +1460,6 @@ function getSizingValue(element, dimension) {
1242
1460
  }
1243
1461
  };
1244
1462
  }
1245
- function getComputedSizing(element) {
1246
- return {
1247
- width: getSizingValue(element, "width"),
1248
- height: getSizingValue(element, "height")
1249
- };
1250
- }
1251
1463
  function sizingValueToCSS(sizing) {
1252
1464
  switch (sizing.mode) {
1253
1465
  case "fill":
@@ -1356,134 +1568,6 @@ function parseColorValue(cssValue) {
1356
1568
  }
1357
1569
  return parseNamedColor(raw);
1358
1570
  }
1359
- var TRANSPARENT_COLOR = { hex: "000000", alpha: 0, raw: "transparent" };
1360
- function isVisibleBorderSide(side) {
1361
- return side.style !== "none" && side.style !== "hidden" && parseFloat(side.width) > 0;
1362
- }
1363
- function hasVisibleOutline(computed) {
1364
- return computed.outlineStyle !== "none" && parseFloat(computed.outlineWidth) > 0;
1365
- }
1366
- function parseVisibleColor(value, fallbackCurrentColor) {
1367
- const raw = value.trim();
1368
- const lowered = raw.toLowerCase();
1369
- if (!raw || lowered === "none" || lowered === "transparent") {
1370
- return null;
1371
- }
1372
- const resolved = /^currentcolor$/i.test(raw) ? fallbackCurrentColor ?? raw : raw;
1373
- const parsed = parseColorValue(resolved);
1374
- if (parsed.alpha <= 0) {
1375
- return null;
1376
- }
1377
- return parsed;
1378
- }
1379
- function addUniqueColor(colors, color) {
1380
- if (!color) return;
1381
- colors.set(`${color.hex}:${color.alpha}`, color);
1382
- }
1383
- function isTextRenderingFormControl(element) {
1384
- if (element instanceof HTMLTextAreaElement) return true;
1385
- if (element instanceof HTMLSelectElement) return true;
1386
- if (element instanceof HTMLButtonElement) return true;
1387
- if (element instanceof HTMLInputElement) {
1388
- const textlessInputTypes = /* @__PURE__ */ new Set([
1389
- "hidden",
1390
- "checkbox",
1391
- "radio",
1392
- "range",
1393
- "color",
1394
- "file",
1395
- "image"
1396
- ]);
1397
- return !textlessInputTypes.has(element.type.toLowerCase());
1398
- }
1399
- return false;
1400
- }
1401
- function hasRenderableTextNode(element) {
1402
- if (element.isContentEditable) return true;
1403
- if (isTextRenderingFormControl(element)) return true;
1404
- if (!element.textContent?.trim()) return false;
1405
- if (hasDirectNonWhitespaceText(element)) return true;
1406
- const tagName = element.tagName.toLowerCase();
1407
- return TEXT_ELEMENT_TAGS.has(tagName) || element.children.length === 0;
1408
- }
1409
- function getComputedBoxShadow(element) {
1410
- const computed = window.getComputedStyle(element);
1411
- const value = computed.boxShadow.trim();
1412
- return value || "none";
1413
- }
1414
- function getComputedColorStyles(element) {
1415
- const computed = window.getComputedStyle(element);
1416
- const borderSides = [
1417
- { style: computed.borderTopStyle, width: computed.borderTopWidth, color: computed.borderTopColor },
1418
- { style: computed.borderRightStyle, width: computed.borderRightWidth, color: computed.borderRightColor },
1419
- { style: computed.borderBottomStyle, width: computed.borderBottomWidth, color: computed.borderBottomColor },
1420
- { style: computed.borderLeftStyle, width: computed.borderLeftWidth, color: computed.borderLeftColor }
1421
- ];
1422
- const visibleBorderSide = borderSides.find((side) => isVisibleBorderSide(side));
1423
- const hasBorder = Boolean(visibleBorderSide);
1424
- const hasOutline = hasVisibleOutline(computed);
1425
- return {
1426
- backgroundColor: parseColorValue(computed.backgroundColor),
1427
- color: parseColorValue(computed.color),
1428
- borderColor: hasBorder && visibleBorderSide ? parseColorValue(visibleBorderSide.color) : TRANSPARENT_COLOR,
1429
- outlineColor: hasOutline ? parseColorValue(computed.outlineColor) : TRANSPARENT_COLOR
1430
- };
1431
- }
1432
- function getSelectionColors(element) {
1433
- const uniqueColors = /* @__PURE__ */ new Map();
1434
- const queue = [element];
1435
- for (let index = 0; index < queue.length; index++) {
1436
- const node = queue[index];
1437
- const computed = window.getComputedStyle(node);
1438
- if (computed.display === "none") {
1439
- continue;
1440
- }
1441
- const isVisibilityHidden = computed.visibility === "hidden" || computed.visibility === "collapse";
1442
- const currentTextColor = computed.color;
1443
- if (!isVisibilityHidden) {
1444
- addUniqueColor(uniqueColors, parseVisibleColor(computed.backgroundColor));
1445
- if (node instanceof HTMLElement && hasRenderableTextNode(node)) {
1446
- addUniqueColor(uniqueColors, parseVisibleColor(currentTextColor));
1447
- }
1448
- const borderSides = [
1449
- { style: computed.borderTopStyle, width: computed.borderTopWidth, color: computed.borderTopColor },
1450
- { style: computed.borderRightStyle, width: computed.borderRightWidth, color: computed.borderRightColor },
1451
- { style: computed.borderBottomStyle, width: computed.borderBottomWidth, color: computed.borderBottomColor },
1452
- { style: computed.borderLeftStyle, width: computed.borderLeftWidth, color: computed.borderLeftColor }
1453
- ];
1454
- for (const side of borderSides) {
1455
- if (!isVisibleBorderSide(side)) continue;
1456
- addUniqueColor(uniqueColors, parseVisibleColor(side.color, currentTextColor));
1457
- }
1458
- if (hasVisibleOutline(computed)) {
1459
- addUniqueColor(uniqueColors, parseVisibleColor(computed.outlineColor, currentTextColor));
1460
- }
1461
- if (node instanceof SVGElement) {
1462
- const fillColor = parseVisibleColor(computed.getPropertyValue("fill"), currentTextColor) ?? parseVisibleColor(node.getAttribute("fill") ?? "", currentTextColor);
1463
- const strokeColor = parseVisibleColor(computed.getPropertyValue("stroke"), currentTextColor) ?? parseVisibleColor(node.getAttribute("stroke") ?? "", currentTextColor);
1464
- addUniqueColor(uniqueColors, fillColor);
1465
- addUniqueColor(uniqueColors, strokeColor);
1466
- }
1467
- }
1468
- for (const child of node.children) {
1469
- queue.push(child);
1470
- }
1471
- }
1472
- return Array.from(uniqueColors.values());
1473
- }
1474
- function getAllComputedStyles(element) {
1475
- const { spacing, borderRadius, flex } = getComputedStyles(element);
1476
- return {
1477
- spacing,
1478
- borderRadius,
1479
- border: getComputedBorderStyles(element),
1480
- flex,
1481
- sizing: getComputedSizing(element),
1482
- color: getComputedColorStyles(element),
1483
- boxShadow: getComputedBoxShadow(element),
1484
- typography: getComputedTypography(element)
1485
- };
1486
- }
1487
1571
  var colorPropertyToCSSMap = {
1488
1572
  backgroundColor: "background-color",
1489
1573
  color: "color",
@@ -1938,7 +2022,7 @@ function findChildAtPoint(parent, clientX, clientY) {
1938
2022
  return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
1939
2023
  });
1940
2024
  if (hit) return hit;
1941
- if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
2025
+ if (children.length === 1 && !hasDirectNonWhitespaceText2(parent)) return children[0];
1942
2026
  return null;
1943
2027
  }
1944
2028
  function elementFromPointWithoutOverlays(x, y) {
@@ -2492,7 +2576,7 @@ function buildElementContext(locator) {
2492
2576
  return buildLocatorContextLines(locator).join("\n");
2493
2577
  }
2494
2578
  function hasSessionEditChanges(edit) {
2495
- return Object.keys(edit.pendingStyles).length > 0 || Boolean(edit.textEdit) || Boolean(edit.move);
2579
+ return Object.keys(edit.pendingStyles).length > 0 || Boolean(edit.textEdit) || Boolean(edit.move) || Boolean(edit.deleted);
2496
2580
  }
2497
2581
  function partitionMultiSelectedEdits(elements, sessionEditsRef) {
2498
2582
  const editsWithChanges = [];
@@ -3014,7 +3098,7 @@ function buildMoveEntries(edits) {
3014
3098
  let noopMoveCount = 0;
3015
3099
  for (const edit of edits) {
3016
3100
  const move = edit.move;
3017
- if (!move) continue;
3101
+ if (!move || edit.deleted) continue;
3018
3102
  const subject = buildAnchorRef(
3019
3103
  getElementDisplayName(edit.element) || edit.locator.tagName,
3020
3104
  edit.locator.domSelector,
@@ -3173,19 +3257,22 @@ function getExportContentProfile(edits, comments, movePlanOrContext) {
3173
3257
  hasCssEdits: edits.some((e) => Object.keys(e.pendingStyles).length > 0),
3174
3258
  hasTextEdits: edits.some((e) => e.textEdit != null),
3175
3259
  hasMoves: moveOpCount > 0,
3176
- hasComments: comments.length > 0
3260
+ hasComments: comments.length > 0,
3261
+ hasDeletes: edits.some((e) => e.deleted)
3177
3262
  };
3178
3263
  }
3179
3264
  function buildExportInstruction(profile) {
3180
3265
  const { hasCssEdits, hasTextEdits, hasMoves, hasComments } = profile;
3181
- if (!hasCssEdits && !hasTextEdits && !hasMoves && !hasComments) return "";
3182
- if (!hasCssEdits && !hasTextEdits && !hasMoves) {
3266
+ const hasDeletes = Boolean(profile.hasDeletes);
3267
+ if (!hasCssEdits && !hasTextEdits && !hasMoves && !hasComments && !hasDeletes) return "";
3268
+ if (!hasCssEdits && !hasTextEdits && !hasMoves && !hasDeletes) {
3183
3269
  return hasComments ? "Address this feedback on the UI. Use the provided source location and selector to find each element in the codebase." : "";
3184
3270
  }
3185
3271
  const parts = [];
3186
3272
  if (hasCssEdits) parts.push("Apply the CSS changes to the targeted elements using the project's existing styling approach (Tailwind, CSS modules, etc.). Map values to existing CSS variables, design tokens, or utility classes already used in the project whenever possible.");
3187
3273
  if (hasTextEdits) parts.push("Update the text content as specified.");
3188
3274
  if (hasMoves) parts.push("Implement the move plan below directly in source code. For `structural_move`, reorder/reparent elements using the target anchors. For `layout_refactor`, apply the listed flex/grid refactor steps. Do NOT simulate movement with absolute positioning, left/top offsets, transform, or margin hacks.");
3275
+ if (hasDeletes) parts.push("Delete the elements marked for deletion from the source code \u2014 remove their markup/JSX (and any now-dead props, handlers, or imports they solely used).");
3189
3276
  if (hasComments) parts.push("Address the comments on the relevant elements.");
3190
3277
  return `${parts.join(" ")} Use the provided source locations, selectors, and context HTML to locate each element in the codebase.`;
3191
3278
  }
@@ -3220,6 +3307,13 @@ function buildSessionExport(edits, comments = [], options) {
3220
3307
  blocks.push(planLines.join("\n"));
3221
3308
  }
3222
3309
  for (const edit of edits) {
3310
+ if (edit.deleted) {
3311
+ const lines = buildLocatorContextLines(edit.locator);
3312
+ lines.push("");
3313
+ lines.push("action: delete this element \u2014 remove it from the source");
3314
+ blocks.push(lines.join("\n"));
3315
+ continue;
3316
+ }
3223
3317
  const moveIntent = getMoveIntentForEdit(edit, planContext);
3224
3318
  const hasMove = Boolean(moveIntent);
3225
3319
  const hasStyleOrText = Object.keys(edit.pendingStyles).length > 0 || edit.textEdit != null;
@@ -4128,6 +4222,7 @@ function useSessionManager({
4128
4222
  sessionEditsRef,
4129
4223
  removedSessionEditsRef,
4130
4224
  undoStackRef,
4225
+ onElementInsertedRef,
4131
4226
  pushUndo,
4132
4227
  setState,
4133
4228
  setSessionEditCount
@@ -4324,27 +4419,48 @@ function useSessionManager({
4324
4419
  selectElement(firstChild);
4325
4420
  }
4326
4421
  }, [getSelectableChild, selectElement]);
4422
+ const centerElementOnBody = React3.useCallback((element, size) => {
4423
+ const bodyRect = document.body.getBoundingClientRect();
4424
+ const scaleX = document.body.offsetWidth > 0 ? bodyRect.width / document.body.offsetWidth : 1;
4425
+ const scaleY = document.body.offsetHeight > 0 ? bodyRect.height / document.body.offsetHeight : 1;
4426
+ const fallbackWidth = size?.width ?? element.offsetWidth ?? 0;
4427
+ const fallbackHeight = size?.height ?? element.offsetHeight ?? 0;
4428
+ const measuredRect = element.getBoundingClientRect();
4429
+ const width = measuredRect.width || fallbackWidth;
4430
+ const height = measuredRect.height || fallbackHeight;
4431
+ const left = Math.round((window.innerWidth / 2 - bodyRect.left) / scaleX - width / 2);
4432
+ const top = Math.round((window.innerHeight / 2 - bodyRect.top) / scaleY - height / 2);
4433
+ element.style.left = `${left}px`;
4434
+ element.style.top = `${top}px`;
4435
+ }, []);
4327
4436
  const insertElement = React3.useCallback((kind) => {
4328
4437
  if (!stateRef.current.editModeActive) return;
4329
4438
  saveCurrentToSession();
4330
4439
  const restoreSelection = buildSelectionSnapshot();
4331
4440
  const selectedEl = stateRef.current.selectedElement;
4332
- const hasSelection = kind === "frame" && selectedEl !== null && selectedEl !== document.body && selectedEl.parentElement !== null;
4333
- const width = kind === "frame" ? 100 : 160;
4334
- const height = kind === "frame" ? 100 : 96;
4335
- const element = document.createElement("div");
4441
+ const insertsAsSibling = kind === "frame" || kind === "text";
4442
+ const hasSelection = insertsAsSibling && selectedEl !== null && selectedEl !== document.body && selectedEl.parentElement !== null;
4443
+ const element = document.createElement(kind === "text" ? "p" : "div");
4336
4444
  element.id = nextGeneratedCanvasId(kind);
4337
4445
  element.setAttribute(GENERATED_CANVAS_NODE_ATTR, kind);
4338
- element.style.width = `${width}px`;
4339
- element.style.height = `${height}px`;
4340
4446
  element.style.boxSizing = "border-box";
4341
4447
  if (kind === "frame") {
4448
+ element.style.width = "100px";
4449
+ element.style.height = "100px";
4342
4450
  element.style.background = "#F5F5F5";
4343
4451
  element.style.border = "1px solid #E0E0E0";
4344
- } else {
4452
+ } else if (kind === "div") {
4453
+ element.style.width = "160px";
4454
+ element.style.height = "96px";
4345
4455
  element.style.borderRadius = "12px";
4346
4456
  element.style.border = "1px solid rgba(13, 153, 255, 0.35)";
4347
4457
  element.style.background = "rgba(13, 153, 255, 0.08)";
4458
+ } else {
4459
+ element.textContent = "Text";
4460
+ element.style.display = "inline-block";
4461
+ element.style.margin = "0";
4462
+ element.style.minHeight = "24px";
4463
+ element.style.textAlign = "center";
4348
4464
  }
4349
4465
  if (hasSelection) {
4350
4466
  const insertionParent = selectedEl.parentElement;
@@ -4355,16 +4471,22 @@ function useSessionManager({
4355
4471
  insertionParent.appendChild(element);
4356
4472
  }
4357
4473
  } else {
4358
- const bodyRect = document.body.getBoundingClientRect();
4359
- const scaleX = document.body.offsetWidth > 0 ? bodyRect.width / document.body.offsetWidth : 1;
4360
- const scaleY = document.body.offsetHeight > 0 ? bodyRect.height / document.body.offsetHeight : 1;
4361
- const left = Math.round((window.innerWidth / 2 - bodyRect.left) / scaleX - width / 2);
4362
- const top = Math.round((window.innerHeight / 2 - bodyRect.top) / scaleY - height / 2);
4363
4474
  element.style.position = "absolute";
4364
- element.style.left = `${left}px`;
4365
- element.style.top = `${top}px`;
4366
4475
  element.style.zIndex = "1";
4367
- document.body.appendChild(element);
4476
+ if (kind === "text") {
4477
+ element.style.left = "0px";
4478
+ element.style.top = "0px";
4479
+ element.style.visibility = "hidden";
4480
+ document.body.appendChild(element);
4481
+ centerElementOnBody(element);
4482
+ element.style.visibility = "";
4483
+ } else {
4484
+ centerElementOnBody(
4485
+ element,
4486
+ kind === "frame" ? { width: 100, height: 100 } : { width: 160, height: 96 }
4487
+ );
4488
+ document.body.appendChild(element);
4489
+ }
4368
4490
  }
4369
4491
  pushUndo({
4370
4492
  type: "structure",
@@ -4379,7 +4501,8 @@ function useSessionManager({
4379
4501
  primaryElement: element,
4380
4502
  pushUndo: false
4381
4503
  });
4382
- }, [applySelection, buildSelectionSnapshot, pushUndo, saveCurrentToSession, stateRef]);
4504
+ onElementInsertedRef.current?.(kind, element);
4505
+ }, [applySelection, buildSelectionSnapshot, centerElementOnBody, onElementInsertedRef, pushUndo, saveCurrentToSession, stateRef]);
4383
4506
  const groupSelection = React3.useCallback(() => {
4384
4507
  const selected = getSanitizedSelection(stateRef.current.selectedElements);
4385
4508
  if (selected.length < 2) return;
@@ -4475,9 +4598,17 @@ function useSessionManager({
4475
4598
  }));
4476
4599
  const sessionSnapshots = /* @__PURE__ */ new Map();
4477
4600
  for (const el of selected) {
4478
- const edit = sessionEditsRef.current.get(el);
4479
- if (edit) sessionSnapshots.set(el, edit);
4480
- sessionEditsRef.current.delete(el);
4601
+ const existing = sessionEditsRef.current.get(el);
4602
+ sessionSnapshots.set(el, existing ?? null);
4603
+ sessionEditsRef.current.set(el, existing ? { ...existing, deleted: true } : {
4604
+ element: el,
4605
+ locator: getElementLocator(el),
4606
+ originalStyles: {},
4607
+ pendingStyles: {},
4608
+ move: null,
4609
+ textEdit: null,
4610
+ deleted: true
4611
+ });
4481
4612
  }
4482
4613
  syncSessionItemCount();
4483
4614
  for (const { element } of snapshots) {
@@ -4498,7 +4629,8 @@ function useSessionManager({
4498
4629
  }
4499
4630
  }
4500
4631
  for (const [el, edit] of sessionSnapshots) {
4501
- sessionEditsRef.current.set(el, edit);
4632
+ if (edit) sessionEditsRef.current.set(el, edit);
4633
+ else sessionEditsRef.current.delete(el);
4502
4634
  }
4503
4635
  syncSessionItemCount();
4504
4636
  }
@@ -4889,7 +5021,7 @@ function useSessionManager({
4889
5021
  saveCurrentToSession();
4890
5022
  const edits = [];
4891
5023
  for (const edit of sessionEditsRef.current.values()) {
4892
- if (!edit.element.isConnected) {
5024
+ if (!edit.element.isConnected && !edit.deleted) {
4893
5025
  sessionEditsRef.current.delete(edit.element);
4894
5026
  continue;
4895
5027
  }
@@ -5058,6 +5190,7 @@ ${exportMarkdown}`);
5058
5190
 
5059
5191
  // src/use-text-and-comments.ts
5060
5192
  var React4 = __toESM(require("react"));
5193
+ var GENERATED_CANVAS_NODE_ATTR2 = "data-made-refine-canvas-node";
5061
5194
  function clampUnit(value) {
5062
5195
  if (!Number.isFinite(value)) return 0;
5063
5196
  return Math.max(0, Math.min(1, value));
@@ -5093,6 +5226,94 @@ function useTextAndComments({
5093
5226
  editingElement.style.outlineOffset = "";
5094
5227
  editingElement.style.cursor = originalCursor;
5095
5228
  editingElement.blur();
5229
+ const isGeneratedTextElement = editingElement.getAttribute(GENERATED_CANVAS_NODE_ATTR2) === "text";
5230
+ const shouldDeleteGeneratedText = isGeneratedTextElement && newText.trim().length === 0;
5231
+ if (shouldDeleteGeneratedText) {
5232
+ const parent = editingElement.parentElement;
5233
+ const nextSibling = editingElement.nextSibling;
5234
+ const current = stateRef.current;
5235
+ const removedComments = current.comments.filter((comment) => comment.element === editingElement);
5236
+ const removedCommentIds = new Set(removedComments.map((comment) => comment.id));
5237
+ const remainingComments = current.comments.filter((comment) => comment.element !== editingElement);
5238
+ const restoredActiveCommentId = current.activeCommentId && removedCommentIds.has(current.activeCommentId) ? current.activeCommentId : null;
5239
+ const existingSessionEdit = existing ? {
5240
+ ...existing,
5241
+ originalStyles: { ...existing.originalStyles },
5242
+ pendingStyles: { ...existing.pendingStyles },
5243
+ move: existing.move ? { ...existing.move } : null,
5244
+ textEdit: existing.textEdit ? { ...existing.textEdit } : null
5245
+ } : null;
5246
+ const restoreSelection = {
5247
+ isOpen: current.isOpen,
5248
+ selectedElement: current.selectedElement,
5249
+ selectedElements: [...current.selectedElements],
5250
+ selectionAnchorElement: current.selectionAnchorElement,
5251
+ originalStyles: { ...current.originalStyles },
5252
+ pendingStyles: { ...current.pendingStyles }
5253
+ };
5254
+ sessionEditsRef.current.delete(editingElement);
5255
+ if (editingElement.isConnected) {
5256
+ editingElement.remove();
5257
+ }
5258
+ pushUndo({
5259
+ type: "structure",
5260
+ restoreSelection,
5261
+ undo: () => {
5262
+ editingElement.textContent = previousText;
5263
+ if (!editingElement.isConnected && parent?.isConnected) {
5264
+ if (nextSibling && nextSibling.parentNode === parent) {
5265
+ parent.insertBefore(editingElement, nextSibling);
5266
+ } else {
5267
+ parent.appendChild(editingElement);
5268
+ }
5269
+ }
5270
+ if (existingSessionEdit) {
5271
+ sessionEditsRef.current.set(editingElement, existingSessionEdit);
5272
+ }
5273
+ setState((prev) => ({
5274
+ ...prev,
5275
+ comments: current.comments,
5276
+ activeCommentId: restoredActiveCommentId ?? prev.activeCommentId
5277
+ }));
5278
+ syncSessionItemCount(current.comments);
5279
+ }
5280
+ });
5281
+ syncSessionItemCount(remainingComments);
5282
+ setState((prev) => {
5283
+ const selectionContainsElement = prev.selectedElement === editingElement || prev.selectionAnchorElement === editingElement || prev.selectedElements.includes(editingElement);
5284
+ if (!selectionContainsElement) {
5285
+ return prev.textEditingElement === editingElement ? {
5286
+ ...prev,
5287
+ comments: prev.comments.filter((comment) => comment.element !== editingElement),
5288
+ activeCommentId: prev.activeCommentId && removedCommentIds.has(prev.activeCommentId) ? null : prev.activeCommentId,
5289
+ textEditingElement: null
5290
+ } : prev;
5291
+ }
5292
+ return {
5293
+ ...prev,
5294
+ isOpen: false,
5295
+ selectedElement: null,
5296
+ selectedElements: [],
5297
+ selectionAnchorElement: null,
5298
+ elementInfo: null,
5299
+ computedSpacing: null,
5300
+ computedBorderRadius: null,
5301
+ computedBorder: null,
5302
+ computedFlex: null,
5303
+ computedSizing: null,
5304
+ computedColor: null,
5305
+ computedBoxShadow: null,
5306
+ computedTypography: null,
5307
+ isComponentPrimitive: false,
5308
+ comments: remainingComments,
5309
+ activeCommentId: restoredActiveCommentId ? null : prev.activeCommentId,
5310
+ originalStyles: {},
5311
+ pendingStyles: {},
5312
+ textEditingElement: null
5313
+ };
5314
+ });
5315
+ return;
5316
+ }
5096
5317
  if (newText !== previousText) {
5097
5318
  pushUndo({ type: "textEdit", element: editingElement, originalText, previousText });
5098
5319
  removedSessionEditsRef.current.delete(editingElement);
@@ -5611,28 +5832,30 @@ async function toClientResponse(response) {
5611
5832
  const data = await readJsonRecord(response);
5612
5833
  const bodyOk = data?.ok;
5613
5834
  const parsedOk = typeof bodyOk === "boolean" ? bodyOk : response.ok;
5835
+ const ok = parsedOk && response.ok;
5614
5836
  return {
5615
- ok: parsedOk && response.ok,
5616
- id: readString(data, "id") ?? ""
5837
+ ok,
5838
+ id: readString(data, "id") ?? "",
5839
+ ...!ok ? { errorKind: "rejected" } : {}
5617
5840
  };
5618
5841
  }
5619
5842
  async function postWithSessionToken(path, payload) {
5620
5843
  const idempotencyKey = createIdempotencyKey();
5621
5844
  let session = await bootstrapSession();
5622
- if (!session) return { ok: false, id: "" };
5845
+ if (!session) return { ok: false, id: "", errorKind: "network" };
5623
5846
  let response;
5624
5847
  try {
5625
5848
  response = await sendAnnotationRequest(session, path, payload, idempotencyKey);
5626
5849
  } catch {
5627
- return { ok: false, id: "" };
5850
+ return { ok: false, id: "", errorKind: "network" };
5628
5851
  }
5629
5852
  if (response.status === 401 || response.status === 403) {
5630
5853
  session = await refreshSessionToken(session) ?? await bootstrapSession(true);
5631
- if (!session) return { ok: false, id: "" };
5854
+ if (!session) return { ok: false, id: "", errorKind: "network" };
5632
5855
  try {
5633
5856
  response = await sendAnnotationRequest(session, path, payload, idempotencyKey);
5634
5857
  } catch {
5635
- return { ok: false, id: "" };
5858
+ return { ok: false, id: "", errorKind: "network" };
5636
5859
  }
5637
5860
  }
5638
5861
  return toClientResponse(response);
@@ -5685,8 +5908,10 @@ function buildLocatorPayload(locator) {
5685
5908
  }
5686
5909
  function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrentToSession, removeSessionEdit, deleteComment }) {
5687
5910
  const [agentAvailable, setAgentAvailable] = React5.useState(false);
5911
+ const [lastSendFailure, setLastSendFailure] = React5.useState(null);
5688
5912
  const isMountedRef = React5.useRef(true);
5689
5913
  React5.useEffect(() => {
5914
+ isMountedRef.current = true;
5690
5915
  return () => {
5691
5916
  isMountedRef.current = false;
5692
5917
  };
@@ -5743,7 +5968,7 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5743
5968
  const resolvedPlanContext = movePlanContext ?? buildMovePlanContext(editsForPlan);
5744
5969
  const includeBatchMoveEnvelope = Boolean(options?.includeBatchMoveEnvelope && sessionEdit.move);
5745
5970
  const isBatchSend = Boolean(allEdits && allEdits.length > 1);
5746
- const exportMarkdown = sessionEdit.move ? buildSessionExport(
5971
+ const exportMarkdown = sessionEdit.move || sessionEdit.deleted ? buildSessionExport(
5747
5972
  includeBatchMoveEnvelope ? editsForPlan : [sessionEdit],
5748
5973
  [],
5749
5974
  {
@@ -5759,7 +5984,7 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5759
5984
  }));
5760
5985
  const moveIntent = sessionEdit.move ? getMoveIntentForEdit(sessionEdit, resolvedPlanContext) : null;
5761
5986
  const movePlan = includeBatchMoveEnvelope ? resolvedPlanContext.movePlan : null;
5762
- const hasMeaningfulPayload = changes.length > 0 || sessionEdit.textEdit != null || moveIntent != null;
5987
+ const hasMeaningfulPayload = changes.length > 0 || sessionEdit.textEdit != null || moveIntent != null || Boolean(sessionEdit.deleted);
5763
5988
  if (!hasMeaningfulPayload) return true;
5764
5989
  const profile = getExportContentProfile(
5765
5990
  [sessionEdit],
@@ -5773,17 +5998,44 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5773
5998
  textChange: sessionEdit.textEdit ?? null,
5774
5999
  moveIntent,
5775
6000
  ...movePlan ? { movePlan } : {},
6001
+ ...sessionEdit.deleted ? { deleted: true } : {},
5776
6002
  exportMarkdown: withInstruction(profile, exportMarkdown)
5777
6003
  });
5778
6004
  if (result.ok) {
5779
6005
  removeSessionEdit(sessionEdit.element);
6006
+ updateAgentAvailability(true);
6007
+ } else {
6008
+ const kind = result.errorKind === "network" ? "unreachable" : "rejected";
6009
+ updateAgentAvailability(result.errorKind === "network" ? false : true);
6010
+ if (options?._isBatchCall) {
6011
+ options._batchFailKinds?.push(result.errorKind ?? "rejected");
6012
+ } else if (isMountedRef.current) {
6013
+ setLastSendFailure({
6014
+ reason: kind,
6015
+ failedEditElements: [sessionEdit.element],
6016
+ failedCommentIds: [],
6017
+ at: Date.now()
6018
+ });
6019
+ }
5780
6020
  }
5781
- return updateAgentAvailability(result.ok);
5782
- } catch {
5783
- return updateAgentAvailability(false);
6021
+ return result.ok;
6022
+ } catch (err) {
6023
+ updateAgentAvailability(false);
6024
+ if (options?._isBatchCall) {
6025
+ throw err;
6026
+ }
6027
+ if (isMountedRef.current) {
6028
+ setLastSendFailure({
6029
+ reason: "unreachable",
6030
+ failedEditElements: [sessionEdit.element],
6031
+ failedCommentIds: [],
6032
+ at: Date.now()
6033
+ });
6034
+ }
6035
+ return false;
5784
6036
  }
5785
6037
  }, [updateAgentAvailability, removeSessionEdit]);
5786
- const sendSessionCommentToAgent = React5.useCallback(async (comment) => {
6038
+ const sendSessionCommentToAgent = React5.useCallback(async (comment, _options) => {
5787
6039
  const exportMarkdown = buildCommentExport(comment.locator, comment.text, comment.replies);
5788
6040
  const commentProfile = { hasCssEdits: false, hasTextEdits: false, hasMoves: false, hasComments: true };
5789
6041
  try {
@@ -5795,13 +6047,40 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5795
6047
  });
5796
6048
  if (result.ok) {
5797
6049
  deleteComment(comment.id);
6050
+ updateAgentAvailability(true);
6051
+ } else {
6052
+ const kind = result.errorKind === "network" ? "unreachable" : "rejected";
6053
+ updateAgentAvailability(result.errorKind === "network" ? false : true);
6054
+ if (_options?._isBatchCall) {
6055
+ _options._batchFailKinds?.push(result.errorKind ?? "rejected");
6056
+ } else if (isMountedRef.current) {
6057
+ setLastSendFailure({
6058
+ reason: kind,
6059
+ failedEditElements: [],
6060
+ failedCommentIds: [comment.id],
6061
+ at: Date.now()
6062
+ });
6063
+ }
5798
6064
  }
5799
- return updateAgentAvailability(result.ok);
5800
- } catch {
5801
- return updateAgentAvailability(false);
6065
+ return result.ok;
6066
+ } catch (err) {
6067
+ updateAgentAvailability(false);
6068
+ if (_options?._isBatchCall) {
6069
+ throw err;
6070
+ }
6071
+ if (isMountedRef.current) {
6072
+ setLastSendFailure({
6073
+ reason: "unreachable",
6074
+ failedEditElements: [],
6075
+ failedCommentIds: [comment.id],
6076
+ at: Date.now()
6077
+ });
6078
+ }
6079
+ return false;
5802
6080
  }
5803
6081
  }, [updateAgentAvailability, deleteComment]);
5804
6082
  const sendEditToAgent2 = React5.useCallback(async () => {
6083
+ if (isMountedRef.current) setLastSendFailure(null);
5805
6084
  const current = stateRef.current;
5806
6085
  if (current.selectedElements.length > 1) {
5807
6086
  saveCurrentToSession();
@@ -5836,9 +6115,28 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5836
6115
  removeSessionEdit(el);
5837
6116
  }
5838
6117
  }
6118
+ updateAgentAvailability(true);
6119
+ } else {
6120
+ updateAgentAvailability(result.errorKind === "network" ? false : true);
6121
+ if (isMountedRef.current) {
6122
+ setLastSendFailure({
6123
+ reason: result.errorKind === "network" ? "unreachable" : "rejected",
6124
+ failedEditElements: editsWithChanges.map((e) => e.element),
6125
+ failedCommentIds: [],
6126
+ at: Date.now()
6127
+ });
6128
+ }
5839
6129
  }
5840
- return updateAgentAvailability(result.ok);
6130
+ return result.ok;
5841
6131
  } catch {
6132
+ if (isMountedRef.current) {
6133
+ setLastSendFailure({
6134
+ reason: "unreachable",
6135
+ failedEditElements: editsWithChanges.map((e) => e.element),
6136
+ failedCommentIds: [],
6137
+ at: Date.now()
6138
+ });
6139
+ }
5842
6140
  return updateAgentAvailability(false);
5843
6141
  }
5844
6142
  }
@@ -5861,11 +6159,13 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5861
6159
  return sendSessionEditToAgent(editToSend);
5862
6160
  }, [canSendEditToAgent, sendSessionEditToAgent, saveCurrentToSession]);
5863
6161
  const sendCommentToAgent2 = React5.useCallback(async (id) => {
6162
+ if (isMountedRef.current) setLastSendFailure(null);
5864
6163
  const comment = stateRef.current.comments.find((c) => c.id === id);
5865
6164
  if (!comment) return false;
5866
6165
  return sendSessionCommentToAgent(comment);
5867
6166
  }, [sendSessionCommentToAgent]);
5868
6167
  const sendAllSessionItemsToAgent = React5.useCallback(async () => {
6168
+ if (isMountedRef.current) setLastSendFailure(null);
5869
6169
  const items = getSessionItems();
5870
6170
  const current = stateRef.current;
5871
6171
  const contextOnlyBlocks = getContextOnlyBlocks(current.selectedElements, items);
@@ -5874,25 +6174,44 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5874
6174
  const movePlanContext = buildMovePlanContext(allEdits);
5875
6175
  let moveEnvelopeSent = false;
5876
6176
  let allSucceeded = true;
6177
+ const failedEditElements = [];
6178
+ const failedCommentIds = [];
6179
+ let anyThrown = false;
6180
+ const batchFailKinds = [];
5877
6181
  for (const item of items) {
5878
6182
  let succeeded;
5879
6183
  if (item.type === "edit") {
5880
6184
  const hasMoveIntent = Boolean(item.edit.move && getMoveIntentForEdit(item.edit, movePlanContext));
5881
6185
  const includeBatchMoveEnvelope = hasMoveIntent && !moveEnvelopeSent;
5882
- succeeded = await sendSessionEditToAgent(
5883
- item.edit,
5884
- allEdits,
5885
- movePlanContext,
5886
- { includeBatchMoveEnvelope }
5887
- );
6186
+ try {
6187
+ succeeded = await sendSessionEditToAgent(
6188
+ item.edit,
6189
+ allEdits,
6190
+ movePlanContext,
6191
+ { includeBatchMoveEnvelope, _isBatchCall: true, _batchFailKinds: batchFailKinds }
6192
+ );
6193
+ if (!succeeded) failedEditElements.push(item.edit.element);
6194
+ } catch {
6195
+ succeeded = false;
6196
+ anyThrown = true;
6197
+ failedEditElements.push(item.edit.element);
6198
+ }
5888
6199
  if (includeBatchMoveEnvelope) moveEnvelopeSent = true;
5889
6200
  } else {
5890
- succeeded = await sendSessionCommentToAgent(item.comment);
6201
+ try {
6202
+ succeeded = await sendSessionCommentToAgent(item.comment, { _isBatchCall: true, _batchFailKinds: batchFailKinds });
6203
+ if (!succeeded) failedCommentIds.push(item.comment.id);
6204
+ } catch {
6205
+ succeeded = false;
6206
+ anyThrown = true;
6207
+ failedCommentIds.push(item.comment.id);
6208
+ }
5891
6209
  }
5892
6210
  if (!succeeded) {
5893
6211
  allSucceeded = false;
5894
6212
  }
5895
6213
  }
6214
+ let contextBlockFailed = false;
5896
6215
  if (contextOnlyBlocks.length > 0) {
5897
6216
  const primaryEl = current.selectedElements.find(
5898
6217
  (el) => el.isConnected && !allEdits.some((e) => e.element === el)
@@ -5906,16 +6225,39 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrent
5906
6225
  moveIntent: null,
5907
6226
  exportMarkdown: contextOnlyBlocks.join("\n\n")
5908
6227
  });
5909
- if (!result.ok) allSucceeded = false;
6228
+ if (result.ok) {
6229
+ updateAgentAvailability(true);
6230
+ } else {
6231
+ updateAgentAvailability(result.errorKind === "network" ? false : true);
6232
+ allSucceeded = false;
6233
+ contextBlockFailed = true;
6234
+ }
5910
6235
  } catch {
6236
+ updateAgentAvailability(false);
5911
6237
  allSucceeded = false;
6238
+ anyThrown = true;
6239
+ contextBlockFailed = true;
5912
6240
  }
5913
6241
  }
5914
6242
  }
6243
+ if (!allSucceeded && isMountedRef.current) {
6244
+ const reason = anyThrown || batchFailKinds.includes("network") ? "unreachable" : "rejected";
6245
+ setLastSendFailure({
6246
+ reason,
6247
+ failedEditElements,
6248
+ failedCommentIds,
6249
+ at: Date.now()
6250
+ });
6251
+ }
5915
6252
  return allSucceeded;
5916
- }, [getSessionItems, sendSessionCommentToAgent, sendSessionEditToAgent]);
6253
+ }, [getSessionItems, sendSessionCommentToAgent, sendSessionEditToAgent, updateAgentAvailability]);
6254
+ const clearSendFailure = React5.useCallback(() => {
6255
+ if (isMountedRef.current) setLastSendFailure(null);
6256
+ }, []);
5917
6257
  return {
5918
6258
  agentAvailable,
6259
+ lastSendFailure,
6260
+ clearSendFailure,
5919
6261
  canSendEditToAgent,
5920
6262
  sendEditToAgent: sendEditToAgent2,
5921
6263
  sendCommentToAgent: sendCommentToAgent2,
@@ -5962,7 +6304,9 @@ function useKeyboardShortcuts({
5962
6304
  const s = stateRef.current;
5963
6305
  const undoShortcutPressed = usesMetaForUndo ? e.metaKey && !e.ctrlKey && !e.altKey : e.ctrlKey && !e.metaKey && !e.altKey;
5964
6306
  if (undoShortcutPressed && e.key === "z" && !e.shiftKey) {
6307
+ if (!s.editModeActive) return;
5965
6308
  if (s.textEditingElement) return;
6309
+ if (isInputFocused()) return;
5966
6310
  e.preventDefault();
5967
6311
  undo();
5968
6312
  return;
@@ -6017,6 +6361,11 @@ function useKeyboardShortcuts({
6017
6361
  insertElement("frame");
6018
6362
  return;
6019
6363
  }
6364
+ if (lowerKey === "t") {
6365
+ e.preventDefault();
6366
+ insertElement("text");
6367
+ return;
6368
+ }
6020
6369
  if (lowerKey === "d") {
6021
6370
  e.preventDefault();
6022
6371
  insertElement("div");
@@ -6679,6 +7028,10 @@ function DirectEditProvider({ children }) {
6679
7028
  const undoStackRef = React8.useRef([]);
6680
7029
  const sessionEditsRef = React8.useRef(/* @__PURE__ */ new Map());
6681
7030
  const removedSessionEditsRef = React8.useRef(/* @__PURE__ */ new WeakSet());
7031
+ const commentDraftTextRef = React8.useRef("");
7032
+ const commentDraftBlockedHandlerRef = React8.useRef(null);
7033
+ const onElementInsertedRef = React8.useRef(null);
7034
+ const textInsertRafRef = React8.useRef(null);
6682
7035
  const [sessionEditCount, setSessionEditCount] = React8.useState(0);
6683
7036
  const stateRef = React8.useRef(state);
6684
7037
  React8.useEffect(() => {
@@ -6713,12 +7066,13 @@ function DirectEditProvider({ children }) {
6713
7066
  clearSessionEdits,
6714
7067
  groupSelection,
6715
7068
  deleteSelection,
6716
- insertElement
7069
+ insertElement: insertElementBase
6717
7070
  } = useSessionManager({
6718
7071
  stateRef,
6719
7072
  sessionEditsRef,
6720
7073
  removedSessionEditsRef,
6721
7074
  undoStackRef,
7075
+ onElementInsertedRef,
6722
7076
  pushUndo,
6723
7077
  setState,
6724
7078
  setSessionEditCount
@@ -6768,6 +7122,41 @@ function DirectEditProvider({ children }) {
6768
7122
  syncSessionItemCount,
6769
7123
  setState
6770
7124
  });
7125
+ React8.useEffect(() => {
7126
+ onElementInsertedRef.current = (kind, element) => {
7127
+ if (kind === "text") {
7128
+ if (textInsertRafRef.current) {
7129
+ cancelAnimationFrame(textInsertRafRef.current);
7130
+ }
7131
+ textInsertRafRef.current = requestAnimationFrame(() => {
7132
+ textInsertRafRef.current = null;
7133
+ if (element.isConnected) {
7134
+ startTextEditing(element);
7135
+ }
7136
+ });
7137
+ }
7138
+ };
7139
+ return () => {
7140
+ if (textInsertRafRef.current) {
7141
+ cancelAnimationFrame(textInsertRafRef.current);
7142
+ textInsertRafRef.current = null;
7143
+ }
7144
+ onElementInsertedRef.current = null;
7145
+ };
7146
+ }, [startTextEditing]);
7147
+ const setCommentDraftText = React8.useCallback((text) => {
7148
+ commentDraftTextRef.current = text;
7149
+ }, []);
7150
+ const setCommentDraftBlockedHandler = React8.useCallback((handler) => {
7151
+ commentDraftBlockedHandlerRef.current = handler;
7152
+ }, []);
7153
+ const hasPendingCommentDraft = React8.useCallback(() => {
7154
+ const activeCommentId = stateRef.current.activeCommentId;
7155
+ if (!activeCommentId) return false;
7156
+ const active = stateRef.current.comments.find((comment) => comment.id === activeCommentId);
7157
+ if (!active) return false;
7158
+ return active.text.trim().length === 0 && commentDraftTextRef.current.trim().length > 0;
7159
+ }, []);
6771
7160
  const { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 } = useCanvas({
6772
7161
  stateRef,
6773
7162
  setState
@@ -6904,6 +7293,8 @@ function DirectEditProvider({ children }) {
6904
7293
  }, [state.editModeActive]);
6905
7294
  const {
6906
7295
  agentAvailable,
7296
+ lastSendFailure,
7297
+ clearSendFailure,
6907
7298
  canSendEditToAgent,
6908
7299
  sendEditToAgent: sendEditToAgent2,
6909
7300
  sendCommentToAgent: sendCommentToAgent2,
@@ -6930,6 +7321,16 @@ function DirectEditProvider({ children }) {
6930
7321
  } catch {
6931
7322
  }
6932
7323
  }, []);
7324
+ const insertElement = React8.useCallback((kind) => {
7325
+ if (hasPendingCommentDraft()) {
7326
+ commentDraftBlockedHandlerRef.current?.();
7327
+ return;
7328
+ }
7329
+ if (stateRef.current.textEditingElement) {
7330
+ commitTextEditing();
7331
+ }
7332
+ insertElementBase(kind);
7333
+ }, [commitTextEditing, hasPendingCommentDraft, insertElementBase, stateRef]);
6933
7334
  useKeyboardShortcuts({
6934
7335
  stateRef,
6935
7336
  toggleEditMode,
@@ -6959,9 +7360,10 @@ function DirectEditProvider({ children }) {
6959
7360
  const stateContextValue = React8.useMemo(() => ({
6960
7361
  ...state,
6961
7362
  agentAvailable,
7363
+ lastSendFailure,
6962
7364
  sessionEditCount,
6963
7365
  multiSelectContextCount
6964
- }), [agentAvailable, state, sessionEditCount, multiSelectContextCount]);
7366
+ }), [agentAvailable, lastSendFailure, state, sessionEditCount, multiSelectContextCount]);
6965
7367
  const actionsContextValue = React8.useMemo(() => ({
6966
7368
  selectElement,
6967
7369
  selectElements,
@@ -6984,6 +7386,7 @@ function DirectEditProvider({ children }) {
6984
7386
  updateTypographyProperty,
6985
7387
  resetToOriginal,
6986
7388
  exportEdits,
7389
+ clearSendFailure,
6987
7390
  canSendEditToAgent,
6988
7391
  sendEditToAgent: sendEditToAgent2,
6989
7392
  sendAllSessionItemsToAgent,
@@ -7008,6 +7411,8 @@ function DirectEditProvider({ children }) {
7008
7411
  removeSessionEdit,
7009
7412
  startTextEditing,
7010
7413
  commitTextEditing,
7414
+ setCommentDraftText,
7415
+ setCommentDraftBlockedHandler,
7011
7416
  groupSelection,
7012
7417
  deleteSelection,
7013
7418
  insertElement,
@@ -7037,6 +7442,7 @@ function DirectEditProvider({ children }) {
7037
7442
  updateTypographyProperty,
7038
7443
  resetToOriginal,
7039
7444
  exportEdits,
7445
+ clearSendFailure,
7040
7446
  canSendEditToAgent,
7041
7447
  sendEditToAgent2,
7042
7448
  sendAllSessionItemsToAgent,
@@ -7061,6 +7467,8 @@ function DirectEditProvider({ children }) {
7061
7467
  removeSessionEdit,
7062
7468
  startTextEditing,
7063
7469
  commitTextEditing,
7470
+ setCommentDraftText,
7471
+ setCommentDraftBlockedHandler,
7064
7472
  groupSelection,
7065
7473
  deleteSelection,
7066
7474
  insertElement,
@@ -7412,10 +7820,223 @@ function createDragInteractionGuard() {
7412
7820
  };
7413
7821
  }
7414
7822
  return {
7415
- activate,
7416
- deactivate
7823
+ activate,
7824
+ deactivate
7825
+ };
7826
+ }
7827
+
7828
+ // src/utils/resize-geometry.ts
7829
+ function toFinite(value, fallback) {
7830
+ if (!Number.isFinite(value)) return fallback;
7831
+ return value;
7832
+ }
7833
+ function multiplyMatrix(left, right) {
7834
+ return {
7835
+ a: left.a * right.a + left.c * right.b,
7836
+ b: left.b * right.a + left.d * right.b,
7837
+ c: left.a * right.c + left.c * right.d,
7838
+ d: left.b * right.c + left.d * right.d
7839
+ };
7840
+ }
7841
+ function splitTransformArgs(raw) {
7842
+ return raw.trim().replace(/,/g, " ").split(/\s+/).filter(Boolean);
7843
+ }
7844
+ function parseAngleRadians(value) {
7845
+ const numeric = Number.parseFloat(value);
7846
+ if (!Number.isFinite(numeric)) return 0;
7847
+ const unit = value.trim().replace(String(numeric), "").trim().toLowerCase();
7848
+ switch (unit) {
7849
+ case "rad":
7850
+ return numeric;
7851
+ case "turn":
7852
+ return numeric * Math.PI * 2;
7853
+ case "grad":
7854
+ return numeric * Math.PI / 200;
7855
+ case "deg":
7856
+ case "":
7857
+ default:
7858
+ return numeric * Math.PI / 180;
7859
+ }
7860
+ }
7861
+ function parseTransformFunction(name, rawArgs) {
7862
+ const args = splitTransformArgs(rawArgs);
7863
+ switch (name.toLowerCase()) {
7864
+ case "matrix": {
7865
+ if (args.length < 4) return null;
7866
+ const [a, b, c, d] = args.map(Number.parseFloat);
7867
+ if (![a, b, c, d].every(Number.isFinite)) return null;
7868
+ return { a, b, c, d };
7869
+ }
7870
+ case "matrix3d": {
7871
+ if (args.length < 16) return null;
7872
+ const values = args.map(Number.parseFloat);
7873
+ if (!values.every(Number.isFinite)) return null;
7874
+ return { a: values[0], b: values[1], c: values[4], d: values[5] };
7875
+ }
7876
+ case "scale": {
7877
+ const scaleX = Number.parseFloat(args[0] ?? "1");
7878
+ const scaleY = Number.parseFloat(args[1] ?? args[0] ?? "1");
7879
+ if (!Number.isFinite(scaleX) || !Number.isFinite(scaleY)) return null;
7880
+ return { a: scaleX, b: 0, c: 0, d: scaleY };
7881
+ }
7882
+ case "scalex": {
7883
+ const scaleX = Number.parseFloat(args[0] ?? "1");
7884
+ if (!Number.isFinite(scaleX)) return null;
7885
+ return { a: scaleX, b: 0, c: 0, d: 1 };
7886
+ }
7887
+ case "scaley": {
7888
+ const scaleY = Number.parseFloat(args[0] ?? "1");
7889
+ if (!Number.isFinite(scaleY)) return null;
7890
+ return { a: 1, b: 0, c: 0, d: scaleY };
7891
+ }
7892
+ case "rotate": {
7893
+ const angle = parseAngleRadians(args[0] ?? "0deg");
7894
+ const cos = Math.cos(angle);
7895
+ const sin = Math.sin(angle);
7896
+ return { a: cos, b: sin, c: -sin, d: cos };
7897
+ }
7898
+ case "translate":
7899
+ case "translatex":
7900
+ case "translatey":
7901
+ return { a: 1, b: 0, c: 0, d: 1 };
7902
+ default:
7903
+ return null;
7904
+ }
7905
+ }
7906
+ function parseTransformMatrix(transform) {
7907
+ const functionPattern = /([a-zA-Z0-9]+)\(([^)]*)\)/g;
7908
+ let matrix = { a: 1, b: 0, c: 0, d: 1 };
7909
+ let matched = false;
7910
+ for (const match of transform.matchAll(functionPattern)) {
7911
+ const next = parseTransformFunction(match[1], match[2]);
7912
+ if (!next) return null;
7913
+ matrix = multiplyMatrix(matrix, next);
7914
+ matched = true;
7915
+ }
7916
+ return matched ? matrix : null;
7917
+ }
7918
+ function scaleFromMatrix(matrix) {
7919
+ return {
7920
+ scaleX: Math.hypot(matrix.a, matrix.b) || 1,
7921
+ scaleY: Math.hypot(matrix.c, matrix.d) || 1
7922
+ };
7923
+ }
7924
+ function getRenderedOffsetScale(element) {
7925
+ const rect = element.getBoundingClientRect();
7926
+ const width = element.offsetWidth;
7927
+ const height = element.offsetHeight;
7928
+ if (width <= 0 || height <= 0 || rect.width <= 0 || rect.height <= 0) return null;
7929
+ return {
7930
+ scaleX: rect.width / width,
7931
+ scaleY: rect.height / height
7932
+ };
7933
+ }
7934
+ function clampSize(value, minSize = 1) {
7935
+ const safeMin = Math.max(1, toFinite(minSize, 1));
7936
+ const safeValue = toFinite(value, safeMin);
7937
+ return Math.max(safeMin, safeValue);
7938
+ }
7939
+ function getElementScale(element) {
7940
+ const transform = getComputedStyle(element).transform;
7941
+ if (!transform || transform === "none") {
7942
+ return getRenderedOffsetScale(element) ?? { scaleX: 1, scaleY: 1 };
7943
+ }
7944
+ let transformMatrix = null;
7945
+ if (typeof DOMMatrix !== "undefined") {
7946
+ try {
7947
+ const matrix = new DOMMatrix(transform);
7948
+ transformMatrix = matrix;
7949
+ } catch {
7950
+ }
7951
+ }
7952
+ transformMatrix = transformMatrix ?? parseTransformMatrix(transform);
7953
+ if (!transformMatrix) return getRenderedOffsetScale(element) ?? { scaleX: 1, scaleY: 1 };
7954
+ const localScale = scaleFromMatrix(transformMatrix);
7955
+ const rect = element.getBoundingClientRect();
7956
+ const width = element.offsetWidth;
7957
+ const height = element.offsetHeight;
7958
+ if (width <= 0 || height <= 0 || rect.width <= 0 || rect.height <= 0) return localScale;
7959
+ const transformedWidth = Math.abs(transformMatrix.a) * width + Math.abs(transformMatrix.c) * height;
7960
+ const transformedHeight = Math.abs(transformMatrix.b) * width + Math.abs(transformMatrix.d) * height;
7961
+ if (transformedWidth <= 0 || transformedHeight <= 0) return localScale;
7962
+ return {
7963
+ scaleX: rect.width / transformedWidth * localScale.scaleX,
7964
+ scaleY: rect.height / transformedHeight * localScale.scaleY
7417
7965
  };
7418
7966
  }
7967
+ function computeEdgeSize({
7968
+ handle,
7969
+ startWidth,
7970
+ startHeight,
7971
+ dx,
7972
+ dy,
7973
+ minSize = 1
7974
+ }) {
7975
+ const baseWidth = clampSize(startWidth, minSize);
7976
+ const baseHeight = clampSize(startHeight, minSize);
7977
+ switch (handle) {
7978
+ case "right":
7979
+ return { width: clampSize(baseWidth + dx, minSize), height: baseHeight };
7980
+ case "left":
7981
+ return { width: clampSize(baseWidth - dx, minSize), height: baseHeight };
7982
+ case "bottom":
7983
+ return { width: baseWidth, height: clampSize(baseHeight + dy, minSize) };
7984
+ case "top":
7985
+ return { width: baseWidth, height: clampSize(baseHeight - dy, minSize) };
7986
+ }
7987
+ }
7988
+ function computeCornerProportionalSize({
7989
+ handle,
7990
+ startWidth,
7991
+ startHeight,
7992
+ dx,
7993
+ dy,
7994
+ minSize = 1
7995
+ }) {
7996
+ const baseWidth = clampSize(startWidth, minSize);
7997
+ const baseHeight = clampSize(startHeight, minSize);
7998
+ const ratio = baseWidth > 0 && baseHeight > 0 ? baseWidth / baseHeight : 1;
7999
+ const widthSign = handle === "top-left" || handle === "bottom-left" ? -1 : 1;
8000
+ const heightSign = handle === "top-left" || handle === "top-right" ? -1 : 1;
8001
+ const rawWidth = baseWidth + widthSign * dx;
8002
+ const rawHeight = baseHeight + heightSign * dy;
8003
+ const widthIntent = clampSize(rawWidth, minSize);
8004
+ const heightIntent = clampSize(rawHeight, minSize);
8005
+ const widthChange = Math.abs(widthIntent - baseWidth) / Math.max(baseWidth, 1);
8006
+ const heightChange = Math.abs(heightIntent - baseHeight) / Math.max(baseHeight, 1);
8007
+ if (widthChange >= heightChange) {
8008
+ const width2 = clampSize(widthIntent, minSize);
8009
+ const height2 = clampSize(width2 / Math.max(ratio, 1e-4), minSize);
8010
+ return { width: width2, height: height2 };
8011
+ }
8012
+ const height = clampSize(heightIntent, minSize);
8013
+ const width = clampSize(height * ratio, minSize);
8014
+ return { width, height };
8015
+ }
8016
+ function computeFillRenderedWidth(element) {
8017
+ const parent = element.parentElement;
8018
+ if (!parent) return null;
8019
+ const parentComputed = window.getComputedStyle(parent);
8020
+ const elementComputed = window.getComputedStyle(element);
8021
+ const parentClientWidth = parent.clientWidth;
8022
+ const parentPaddingLeft = parseFloat(parentComputed.paddingLeft) || 0;
8023
+ const parentPaddingRight = parseFloat(parentComputed.paddingRight) || 0;
8024
+ const parentContentWidth = parentClientWidth - parentPaddingLeft - parentPaddingRight;
8025
+ if (!Number.isFinite(parentContentWidth) || parentContentWidth <= 0) {
8026
+ return null;
8027
+ }
8028
+ const elementPaddingLeft = parseFloat(elementComputed.paddingLeft) || 0;
8029
+ const elementPaddingRight = parseFloat(elementComputed.paddingRight) || 0;
8030
+ const elementBorderLeft = parseFloat(elementComputed.borderLeftWidth) || 0;
8031
+ const elementBorderRight = parseFloat(elementComputed.borderRightWidth) || 0;
8032
+ if (elementComputed.boxSizing === "border-box") {
8033
+ return clampSize(parentContentWidth, 1);
8034
+ }
8035
+ return clampSize(
8036
+ parentContentWidth + elementPaddingLeft + elementPaddingRight + elementBorderLeft + elementBorderRight,
8037
+ 1
8038
+ );
8039
+ }
7419
8040
 
7420
8041
  // src/use-move.ts
7421
8042
  var INITIAL_DRAG_STATE = {
@@ -7489,10 +8110,14 @@ function useMove({ onMoveComplete }) {
7489
8110
  const onMoveCompleteRef = React12.useRef(onMoveComplete);
7490
8111
  const dragOptionsRef = React12.useRef(DEFAULT_DRAG_OPTIONS);
7491
8112
  const dragGuardRef = React12.useRef(createDragInteractionGuard());
7492
- const initialRectRef = React12.useRef(
7493
- { x: 0, y: 0, scaleX: 1, scaleY: 1 }
7494
- );
8113
+ const initialRectRef = React12.useRef({
8114
+ x: 0,
8115
+ y: 0,
8116
+ scaleX: 1,
8117
+ scaleY: 1
8118
+ });
7495
8119
  const originalTransformRef = React12.useRef("");
8120
+ const composeBaseRef = React12.useRef("");
7496
8121
  const reorderPreviewRef = React12.useRef(/* @__PURE__ */ new Map());
7497
8122
  React12.useEffect(() => {
7498
8123
  dragStateRef.current = dragState;
@@ -7506,79 +8131,85 @@ function useMove({ onMoveComplete }) {
7506
8131
  }
7507
8132
  reorderPreviewRef.current.clear();
7508
8133
  }, []);
7509
- const setReorderPreviewTransform = React12.useCallback((element, transform) => {
7510
- const existing = reorderPreviewRef.current.get(element);
7511
- if (!existing) {
7512
- reorderPreviewRef.current.set(element, {
7513
- transform: element.style.transform,
7514
- transition: element.style.transition
7515
- });
7516
- }
7517
- const originalTransition = reorderPreviewRef.current.get(element)?.transition ?? element.style.transition;
7518
- element.style.transition = withTransformTransition(originalTransition);
7519
- element.style.transform = transform;
7520
- }, []);
7521
- const applyReorderPreview = React12.useCallback((target, draggedElement, originalParent) => {
7522
- if (!target || !draggedElement) {
7523
- clearReorderPreview();
7524
- return;
7525
- }
7526
- const container = target.container;
7527
- const containerChildren = Array.from(container.children).filter(
7528
- (child) => child instanceof HTMLElement
7529
- );
7530
- const siblings = containerChildren.filter((child) => child !== draggedElement);
7531
- const insertIndex = getInsertIndex(siblings, target.insertBefore);
7532
- if (insertIndex === null) {
7533
- clearReorderPreview();
7534
- return;
7535
- }
7536
- const draggedRect = draggedElement.getBoundingClientRect();
7537
- const isHorizontal = isHorizontalDirection(target.flexDirection);
7538
- const dragSize = isHorizontal ? draggedRect.width : draggedRect.height;
7539
- if (!Number.isFinite(dragSize) || dragSize <= 0) {
7540
- clearReorderPreview();
7541
- return;
7542
- }
7543
- const sign = forwardVisualSign(target.flexDirection);
7544
- const shiftedElements = /* @__PURE__ */ new Map();
7545
- if (container === originalParent) {
7546
- const originalIndex = containerChildren.indexOf(draggedElement);
7547
- if (originalIndex >= 0) {
7548
- if (insertIndex > originalIndex) {
7549
- const shift = -sign * dragSize;
7550
- for (let i = originalIndex; i < insertIndex; i++) {
7551
- const sibling = siblings[i];
7552
- if (sibling) shiftedElements.set(sibling, shift);
7553
- }
7554
- } else if (insertIndex < originalIndex) {
7555
- const shift = sign * dragSize;
7556
- for (let i = insertIndex; i < originalIndex; i++) {
7557
- const sibling = siblings[i];
7558
- if (sibling) shiftedElements.set(sibling, shift);
8134
+ const setReorderPreviewTransform = React12.useCallback(
8135
+ (element, transform) => {
8136
+ const existing = reorderPreviewRef.current.get(element);
8137
+ if (!existing) {
8138
+ reorderPreviewRef.current.set(element, {
8139
+ transform: element.style.transform,
8140
+ transition: element.style.transition
8141
+ });
8142
+ }
8143
+ const originalTransition = reorderPreviewRef.current.get(element)?.transition ?? element.style.transition;
8144
+ element.style.transition = withTransformTransition(originalTransition);
8145
+ element.style.transform = transform;
8146
+ },
8147
+ []
8148
+ );
8149
+ const applyReorderPreview = React12.useCallback(
8150
+ (target, draggedElement, originalParent) => {
8151
+ if (!target || !draggedElement) {
8152
+ clearReorderPreview();
8153
+ return;
8154
+ }
8155
+ const container = target.container;
8156
+ const containerChildren = Array.from(container.children).filter(
8157
+ (child) => child instanceof HTMLElement
8158
+ );
8159
+ const siblings = containerChildren.filter((child) => child !== draggedElement);
8160
+ const insertIndex = getInsertIndex(siblings, target.insertBefore);
8161
+ if (insertIndex === null) {
8162
+ clearReorderPreview();
8163
+ return;
8164
+ }
8165
+ const draggedRect = draggedElement.getBoundingClientRect();
8166
+ const isHorizontal = isHorizontalDirection(target.flexDirection);
8167
+ const dragSize = isHorizontal ? draggedRect.width : draggedRect.height;
8168
+ if (!Number.isFinite(dragSize) || dragSize <= 0) {
8169
+ clearReorderPreview();
8170
+ return;
8171
+ }
8172
+ const sign = forwardVisualSign(target.flexDirection);
8173
+ const shiftedElements = /* @__PURE__ */ new Map();
8174
+ if (container === originalParent) {
8175
+ const originalIndex = containerChildren.indexOf(draggedElement);
8176
+ if (originalIndex >= 0) {
8177
+ if (insertIndex > originalIndex) {
8178
+ const shift = -sign * dragSize;
8179
+ for (let i = originalIndex; i < insertIndex; i++) {
8180
+ const sibling = siblings[i];
8181
+ if (sibling) shiftedElements.set(sibling, shift);
8182
+ }
8183
+ } else if (insertIndex < originalIndex) {
8184
+ const shift = sign * dragSize;
8185
+ for (let i = insertIndex; i < originalIndex; i++) {
8186
+ const sibling = siblings[i];
8187
+ if (sibling) shiftedElements.set(sibling, shift);
8188
+ }
7559
8189
  }
7560
8190
  }
8191
+ } else {
8192
+ const shift = sign * dragSize;
8193
+ for (let i = insertIndex; i < siblings.length; i++) {
8194
+ shiftedElements.set(siblings[i], shift);
8195
+ }
7561
8196
  }
7562
- } else {
7563
- const shift = sign * dragSize;
7564
- for (let i = insertIndex; i < siblings.length; i++) {
7565
- shiftedElements.set(siblings[i], shift);
8197
+ const axis = isHorizontal ? "x" : "y";
8198
+ const keep = new Set(shiftedElements.keys());
8199
+ for (const [element, snapshot2] of reorderPreviewRef.current) {
8200
+ if (!keep.has(element)) {
8201
+ element.style.transform = snapshot2.transform;
8202
+ element.style.transition = snapshot2.transition;
8203
+ reorderPreviewRef.current.delete(element);
8204
+ }
7566
8205
  }
7567
- }
7568
- const axis = isHorizontal ? "x" : "y";
7569
- const keep = new Set(shiftedElements.keys());
7570
- for (const [element, snapshot2] of reorderPreviewRef.current) {
7571
- if (!keep.has(element)) {
7572
- element.style.transform = snapshot2.transform;
7573
- element.style.transition = snapshot2.transition;
7574
- reorderPreviewRef.current.delete(element);
8206
+ for (const [element, shift] of shiftedElements) {
8207
+ const baseTransform = reorderPreviewRef.current.get(element)?.transform ?? element.style.transform;
8208
+ setReorderPreviewTransform(element, withAxisTranslate(baseTransform, axis, shift));
7575
8209
  }
7576
- }
7577
- for (const [element, shift] of shiftedElements) {
7578
- const baseTransform = reorderPreviewRef.current.get(element)?.transform ?? element.style.transform;
7579
- setReorderPreviewTransform(element, withAxisTranslate(baseTransform, axis, shift));
7580
- }
7581
- }, [clearReorderPreview, setReorderPreviewTransform]);
8210
+ },
8211
+ [clearReorderPreview, setReorderPreviewTransform]
8212
+ );
7582
8213
  const cancelDrag = React12.useCallback(() => {
7583
8214
  const current = dragStateRef.current;
7584
8215
  if (current.draggedElement) {
@@ -7587,6 +8218,7 @@ function useMove({ onMoveComplete }) {
7587
8218
  }
7588
8219
  clearReorderPreview();
7589
8220
  originalTransformRef.current = "";
8221
+ composeBaseRef.current = "";
7590
8222
  initialRectRef.current = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
7591
8223
  dragOptionsRef.current = DEFAULT_DRAG_OPTIONS;
7592
8224
  dragGuardRef.current.deactivate();
@@ -7608,6 +8240,7 @@ function useMove({ onMoveComplete }) {
7608
8240
  draggedElement.style.opacity = "";
7609
8241
  clearReorderPreview();
7610
8242
  originalTransformRef.current = "";
8243
+ composeBaseRef.current = "";
7611
8244
  initialRectRef.current = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
7612
8245
  const dragMode = dragOptionsRef.current.mode;
7613
8246
  dragOptionsRef.current = DEFAULT_DRAG_OPTIONS;
@@ -7636,7 +8269,13 @@ function useMove({ onMoveComplete }) {
7636
8269
  const deltaX = (current.ghostPosition.x - rect.left) / scaleX;
7637
8270
  const deltaY = (current.ghostPosition.y - rect.top) / scaleY;
7638
8271
  if ((Math.abs(deltaX) > 0.5 || Math.abs(deltaY) > 0.5) && originalParent) {
7639
- moveInfo = { originalParent, originalPreviousSibling, originalNextSibling, mode: "position", positionDelta: { x: deltaX, y: deltaY } };
8272
+ moveInfo = {
8273
+ originalParent,
8274
+ originalPreviousSibling,
8275
+ originalNextSibling,
8276
+ mode: "position",
8277
+ positionDelta: { x: deltaX, y: deltaY }
8278
+ };
7640
8279
  }
7641
8280
  }
7642
8281
  } else if (target && tryReparent(draggedElement, target, originalParent, originalNextSibling)) {
@@ -7662,13 +8301,21 @@ function useMove({ onMoveComplete }) {
7662
8301
  const previousSibling = element.previousElementSibling;
7663
8302
  const nextSibling = element.nextElementSibling;
7664
8303
  dragOptionsRef.current = normalizeStartDragOptions(options);
8304
+ const { scaleX, scaleY } = getElementScale(element);
7665
8305
  initialRectRef.current = {
7666
8306
  x: rect.left,
7667
8307
  y: rect.top,
7668
- scaleX: element.offsetWidth > 0 ? rect.width / element.offsetWidth : 1,
7669
- scaleY: element.offsetHeight > 0 ? rect.height / element.offsetHeight : 1
8308
+ scaleX,
8309
+ scaleY
7670
8310
  };
7671
- originalTransformRef.current = element.style.transform;
8311
+ const inlineTransform = element.style.transform;
8312
+ originalTransformRef.current = inlineTransform;
8313
+ if (inlineTransform) {
8314
+ composeBaseRef.current = inlineTransform;
8315
+ } else {
8316
+ const computed = getComputedStyle(element).transform;
8317
+ composeBaseRef.current = computed && computed !== "none" ? computed : "";
8318
+ }
7672
8319
  dragGuardRef.current.activate();
7673
8320
  setDragState({
7674
8321
  isDragging: true,
@@ -7701,7 +8348,8 @@ function useMove({ onMoveComplete }) {
7701
8348
  const { x, y, scaleX, scaleY } = initialRectRef.current;
7702
8349
  const dx = (e.clientX - dragOffset.x - x) / scaleX;
7703
8350
  const dy = (e.clientY - dragOffset.y - y) / scaleY;
7704
- draggedElement.style.transform = `translate(${dx}px, ${dy}px)`;
8351
+ const base = composeBaseRef.current;
8352
+ draggedElement.style.transform = base ? `translate(${dx}px, ${dy}px) ${base}` : `translate(${dx}px, ${dy}px)`;
7705
8353
  }
7706
8354
  if (dragOptionsRef.current.mode === "position") {
7707
8355
  let container2 = findLayoutContainerAtPoint(
@@ -7742,19 +8390,9 @@ function useMove({ onMoveComplete }) {
7742
8390
  }
7743
8391
  return;
7744
8392
  }
7745
- const container = dragOptionsRef.current.constrainToOriginalParent ? originalParent : findContainerAtPoint(
7746
- e.clientX,
7747
- e.clientY,
7748
- draggedElement,
7749
- originalParent
7750
- );
8393
+ const container = dragOptionsRef.current.constrainToOriginalParent ? originalParent : findContainerAtPoint(e.clientX, e.clientY, draggedElement, originalParent);
7751
8394
  if (container && draggedElement) {
7752
- const dropPos = calculateDropPosition(
7753
- container,
7754
- e.clientX,
7755
- e.clientY,
7756
- draggedElement
7757
- );
8395
+ const dropPos = calculateDropPosition(container, e.clientX, e.clientY, draggedElement);
7758
8396
  if (dropPos) {
7759
8397
  const nextTarget = {
7760
8398
  container,
@@ -8127,7 +8765,10 @@ function isSelectableElement(element) {
8127
8765
  if (!(element instanceof HTMLElement)) return false;
8128
8766
  if (!element.isConnected) return false;
8129
8767
  if (element === document.body || element === document.documentElement) return false;
8130
- if (element.matches("[data-direct-edit], [data-direct-edit-host], script, style, link, meta, noscript")) return false;
8768
+ if (element.matches(
8769
+ "[data-direct-edit], [data-direct-edit-host], script, style, link, meta, noscript"
8770
+ ))
8771
+ return false;
8131
8772
  const rect = element.getBoundingClientRect();
8132
8773
  if (rect.width <= 0 || rect.height <= 0) return false;
8133
8774
  const computed = window.getComputedStyle(element);
@@ -8145,7 +8786,9 @@ function compareDomOrder2(a, b) {
8145
8786
  }
8146
8787
  function collectMarqueeTargets(rect) {
8147
8788
  const hits = Array.from(document.querySelectorAll("*")).filter(isSelectableElement).filter((element) => rectsIntersect(rect, element.getBoundingClientRect()));
8148
- const deepestHits = hits.filter((element) => !hits.some((other) => other !== element && element.contains(other)));
8789
+ const deepestHits = hits.filter(
8790
+ (element) => !hits.some((other) => other !== element && element.contains(other))
8791
+ );
8149
8792
  deepestHits.sort(compareDomOrder2);
8150
8793
  return deepestHits;
8151
8794
  }
@@ -8568,6 +9211,7 @@ function SelectedCommentComposer({
8568
9211
  comment,
8569
9212
  attentionNonce,
8570
9213
  draftRef,
9214
+ onDraftTextChange,
8571
9215
  onSubmit,
8572
9216
  onCancel
8573
9217
  }) {
@@ -8613,7 +9257,8 @@ function SelectedCommentComposer({
8613
9257
  }, [attentionNonce]);
8614
9258
  React17.useEffect(() => {
8615
9259
  if (draftRef) draftRef.current = text;
8616
- }, [draftRef, text]);
9260
+ onDraftTextChange?.(text);
9261
+ }, [draftRef, onDraftTextChange, text]);
8617
9262
  const submit = React17.useCallback(() => {
8618
9263
  const nextText = text.trim();
8619
9264
  if (!nextText) return;
@@ -8672,161 +9317,89 @@ function SelectedCommentComposer({
8672
9317
  } else if (e.key === "Escape") {
8673
9318
  onCancel();
8674
9319
  }
8675
- }
8676
- }
8677
- ),
8678
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
8679
- Button,
8680
- {
8681
- type: "button",
8682
- variant: "ghost",
8683
- size: "icon",
8684
- className: cn(
8685
- "size-7 shrink-0 self-start",
8686
- text.trim() ? "bg-blue-500 text-white hover:bg-blue-600" : "bg-muted text-muted-foreground"
8687
- ),
8688
- disabled: !text.trim(),
8689
- onClick: submit,
8690
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.ArrowUp, {})
8691
- }
8692
- )
8693
- ]
8694
- }
8695
- );
8696
- }
8697
-
8698
- // src/move-overlay.tsx
8699
- var import_jsx_runtime8 = require("react/jsx-runtime");
8700
- var BLUE2 = "#0D99FF";
8701
- function MoveOverlay({ dropIndicator }) {
8702
- if (!dropIndicator) {
8703
- return null;
8704
- }
8705
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
8706
- "svg",
8707
- {
8708
- "data-direct-edit": "move-overlay",
8709
- style: {
8710
- position: "fixed",
8711
- inset: 0,
8712
- width: "100vw",
8713
- height: "100vh",
8714
- pointerEvents: "none",
8715
- zIndex: 99997
8716
- },
8717
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
8718
- "rect",
8719
- {
8720
- x: dropIndicator.x,
8721
- y: dropIndicator.y,
8722
- width: dropIndicator.width,
8723
- height: dropIndicator.height,
8724
- fill: BLUE2
8725
- }
8726
- )
8727
- }
8728
- );
8729
- }
8730
-
8731
- // src/selection-overlay.tsx
8732
- var React19 = __toESM(require("react"));
8733
- var import_lucide_react2 = require("lucide-react");
8734
-
8735
- // src/use-selection-resize.ts
8736
- var React18 = __toESM(require("react"));
8737
-
8738
- // src/utils/resize-geometry.ts
8739
- function toFinite(value, fallback) {
8740
- if (!Number.isFinite(value)) return fallback;
8741
- return value;
8742
- }
8743
- function clampSize(value, minSize = 1) {
8744
- const safeMin = Math.max(1, toFinite(minSize, 1));
8745
- const safeValue = toFinite(value, safeMin);
8746
- return Math.max(safeMin, safeValue);
8747
- }
8748
- function computeEdgeSize({
8749
- handle,
8750
- startWidth,
8751
- startHeight,
8752
- dx,
8753
- dy,
8754
- minSize = 1
8755
- }) {
8756
- const baseWidth = clampSize(startWidth, minSize);
8757
- const baseHeight = clampSize(startHeight, minSize);
8758
- switch (handle) {
8759
- case "right":
8760
- return { width: clampSize(baseWidth + dx, minSize), height: baseHeight };
8761
- case "left":
8762
- return { width: clampSize(baseWidth - dx, minSize), height: baseHeight };
8763
- case "bottom":
8764
- return { width: baseWidth, height: clampSize(baseHeight + dy, minSize) };
8765
- case "top":
8766
- return { width: baseWidth, height: clampSize(baseHeight - dy, minSize) };
8767
- }
8768
- }
8769
- function computeCornerProportionalSize({
8770
- handle,
8771
- startWidth,
8772
- startHeight,
8773
- dx,
8774
- dy,
8775
- minSize = 1
8776
- }) {
8777
- const baseWidth = clampSize(startWidth, minSize);
8778
- const baseHeight = clampSize(startHeight, minSize);
8779
- const ratio = baseWidth > 0 && baseHeight > 0 ? baseWidth / baseHeight : 1;
8780
- const widthSign = handle === "top-left" || handle === "bottom-left" ? -1 : 1;
8781
- const heightSign = handle === "top-left" || handle === "top-right" ? -1 : 1;
8782
- const rawWidth = baseWidth + widthSign * dx;
8783
- const rawHeight = baseHeight + heightSign * dy;
8784
- const widthIntent = clampSize(rawWidth, minSize);
8785
- const heightIntent = clampSize(rawHeight, minSize);
8786
- const widthChange = Math.abs(widthIntent - baseWidth) / Math.max(baseWidth, 1);
8787
- const heightChange = Math.abs(heightIntent - baseHeight) / Math.max(baseHeight, 1);
8788
- if (widthChange >= heightChange) {
8789
- const width2 = clampSize(widthIntent, minSize);
8790
- const height2 = clampSize(width2 / Math.max(ratio, 1e-4), minSize);
8791
- return { width: width2, height: height2 };
8792
- }
8793
- const height = clampSize(heightIntent, minSize);
8794
- const width = clampSize(height * ratio, minSize);
8795
- return { width, height };
9320
+ }
9321
+ }
9322
+ ),
9323
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
9324
+ Button,
9325
+ {
9326
+ type: "button",
9327
+ variant: "ghost",
9328
+ size: "icon",
9329
+ className: cn(
9330
+ "size-7 shrink-0 self-start",
9331
+ text.trim() ? "bg-blue-500 text-white hover:bg-blue-600" : "bg-muted text-muted-foreground"
9332
+ ),
9333
+ disabled: !text.trim(),
9334
+ onClick: submit,
9335
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.ArrowUp, {})
9336
+ }
9337
+ )
9338
+ ]
9339
+ }
9340
+ );
8796
9341
  }
8797
- function computeFillRenderedWidth(element) {
8798
- const parent = element.parentElement;
8799
- if (!parent) return null;
8800
- const parentComputed = window.getComputedStyle(parent);
8801
- const elementComputed = window.getComputedStyle(element);
8802
- const parentClientWidth = parent.clientWidth;
8803
- const parentPaddingLeft = parseFloat(parentComputed.paddingLeft) || 0;
8804
- const parentPaddingRight = parseFloat(parentComputed.paddingRight) || 0;
8805
- const parentContentWidth = parentClientWidth - parentPaddingLeft - parentPaddingRight;
8806
- if (!Number.isFinite(parentContentWidth) || parentContentWidth <= 0) {
9342
+
9343
+ // src/move-overlay.tsx
9344
+ var import_jsx_runtime8 = require("react/jsx-runtime");
9345
+ var BLUE2 = "#0D99FF";
9346
+ function MoveOverlay({ dropIndicator }) {
9347
+ if (!dropIndicator) {
8807
9348
  return null;
8808
9349
  }
8809
- const elementPaddingLeft = parseFloat(elementComputed.paddingLeft) || 0;
8810
- const elementPaddingRight = parseFloat(elementComputed.paddingRight) || 0;
8811
- const elementBorderLeft = parseFloat(elementComputed.borderLeftWidth) || 0;
8812
- const elementBorderRight = parseFloat(elementComputed.borderRightWidth) || 0;
8813
- if (elementComputed.boxSizing === "border-box") {
8814
- return clampSize(parentContentWidth, 1);
8815
- }
8816
- return clampSize(
8817
- parentContentWidth + elementPaddingLeft + elementPaddingRight + elementBorderLeft + elementBorderRight,
8818
- 1
9350
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
9351
+ "svg",
9352
+ {
9353
+ "data-direct-edit": "move-overlay",
9354
+ style: {
9355
+ position: "fixed",
9356
+ inset: 0,
9357
+ width: "100vw",
9358
+ height: "100vh",
9359
+ pointerEvents: "none",
9360
+ zIndex: 99997
9361
+ },
9362
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
9363
+ "rect",
9364
+ {
9365
+ x: dropIndicator.x,
9366
+ y: dropIndicator.y,
9367
+ width: dropIndicator.width,
9368
+ height: dropIndicator.height,
9369
+ fill: BLUE2
9370
+ }
9371
+ )
9372
+ }
8819
9373
  );
8820
9374
  }
8821
9375
 
9376
+ // src/selection-overlay.tsx
9377
+ var React19 = __toESM(require("react"));
9378
+ var import_lucide_react2 = require("lucide-react");
9379
+
8822
9380
  // src/use-selection-resize.ts
9381
+ var React18 = __toESM(require("react"));
8823
9382
  var MIN_SIZE_PX = 1;
8824
9383
  var SNAP_IN_PX = 2;
8825
9384
  var SNAP_OUT_PX = 6;
8826
9385
  var EPSILON = 1e-4;
8827
9386
  var EDGE_HANDLES = /* @__PURE__ */ new Set(["top", "right", "bottom", "left"]);
8828
- var WIDTH_HANDLES = /* @__PURE__ */ new Set(["left", "right", "top-left", "top-right", "bottom-left", "bottom-right"]);
8829
- var HEIGHT_HANDLES = /* @__PURE__ */ new Set(["top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right"]);
9387
+ var WIDTH_HANDLES = /* @__PURE__ */ new Set([
9388
+ "left",
9389
+ "right",
9390
+ "top-left",
9391
+ "top-right",
9392
+ "bottom-left",
9393
+ "bottom-right"
9394
+ ]);
9395
+ var HEIGHT_HANDLES = /* @__PURE__ */ new Set([
9396
+ "top",
9397
+ "bottom",
9398
+ "top-left",
9399
+ "top-right",
9400
+ "bottom-left",
9401
+ "bottom-right"
9402
+ ]);
8830
9403
  function createSizingValue(mode, numericValue) {
8831
9404
  const rounded = Math.max(MIN_SIZE_PX, Math.round(clampSize(numericValue, MIN_SIZE_PX)));
8832
9405
  return {
@@ -8848,125 +9421,135 @@ function useSelectionResize({
8848
9421
  }) {
8849
9422
  const cleanupRef = React18.useRef(null);
8850
9423
  const txCounterRef = React18.useRef(0);
8851
- const emitSizingChange = React18.useCallback((changes, options) => {
8852
- onResizeSizingChange?.(changes, options);
8853
- }, [onResizeSizingChange]);
9424
+ const emitSizingChange = React18.useCallback(
9425
+ (changes, options) => {
9426
+ onResizeSizingChange?.(changes, options);
9427
+ },
9428
+ [onResizeSizingChange]
9429
+ );
8854
9430
  React18.useEffect(() => {
8855
9431
  return () => {
8856
9432
  cleanupRef.current?.();
8857
9433
  cleanupRef.current = null;
8858
9434
  };
8859
9435
  }, []);
8860
- const getResizeHandlePointerDown = React18.useCallback((handle) => {
8861
- return (e) => {
8862
- if (!enabled || !onResizeSizingChange) return;
8863
- if (e.button !== 0) return;
8864
- e.preventDefault();
8865
- e.stopPropagation();
8866
- cleanupRef.current?.();
8867
- const rect = selectedElement.getBoundingClientRect();
8868
- const offsetWidth = selectedElement.offsetWidth;
8869
- const offsetHeight = selectedElement.offsetHeight;
8870
- const startWidth = clampSize(offsetWidth > 0 ? offsetWidth : rect.width, MIN_SIZE_PX);
8871
- const startHeight = clampSize(offsetHeight > 0 ? offsetHeight : rect.height, MIN_SIZE_PX);
8872
- const scaleX = Math.max(EPSILON, offsetWidth > 0 ? rect.width / offsetWidth : 1);
8873
- const scaleY = Math.max(EPSILON, offsetHeight > 0 ? rect.height / offsetHeight : 1);
8874
- const transactionId = `resize-${Date.now()}-${txCounterRef.current++}`;
8875
- const state = {
8876
- transactionId,
8877
- handle,
8878
- startClientX: e.clientX,
8879
- startClientY: e.clientY,
8880
- startWidth,
8881
- startHeight,
8882
- scaleX,
8883
- scaleY,
8884
- fillTargetWidth: computeFillRenderedWidth(selectedElement),
8885
- fillLocked: detectSizingMode(selectedElement, "width") === "fill"
8886
- };
8887
- emitSizingChange({}, { transactionId: state.transactionId, phase: "start" });
8888
- const onPointerMove = (moveEvent) => {
8889
- const dx = (moveEvent.clientX - state.startClientX) / state.scaleX;
8890
- const dy = (moveEvent.clientY - state.startClientY) / state.scaleY;
8891
- const nextSize = isEdgeHandle(state.handle) ? computeEdgeSize({
8892
- handle: state.handle,
8893
- startWidth: state.startWidth,
8894
- startHeight: state.startHeight,
8895
- dx,
8896
- dy,
8897
- minSize: MIN_SIZE_PX
8898
- }) : computeCornerProportionalSize({
8899
- handle: state.handle,
8900
- startWidth: state.startWidth,
8901
- startHeight: state.startHeight,
8902
- dx,
8903
- dy,
8904
- minSize: MIN_SIZE_PX
8905
- });
8906
- const nextWidth = Math.max(MIN_SIZE_PX, Math.round(nextSize.width));
8907
- const nextHeight = Math.max(MIN_SIZE_PX, Math.round(nextSize.height));
8908
- const changes = {};
8909
- if (WIDTH_HANDLES.has(state.handle)) {
8910
- if (state.fillTargetWidth !== null) {
8911
- const distance = Math.abs(nextWidth - state.fillTargetWidth);
8912
- if (state.fillLocked) {
8913
- if (distance > SNAP_OUT_PX) {
8914
- state.fillLocked = false;
9436
+ const getResizeHandlePointerDown = React18.useCallback(
9437
+ (handle) => {
9438
+ return (e) => {
9439
+ if (!enabled || !onResizeSizingChange) return;
9440
+ if (e.button !== 0) return;
9441
+ e.preventDefault();
9442
+ e.stopPropagation();
9443
+ cleanupRef.current?.();
9444
+ const rect = selectedElement.getBoundingClientRect();
9445
+ const offsetWidth = selectedElement.offsetWidth;
9446
+ const offsetHeight = selectedElement.offsetHeight;
9447
+ const startWidth = clampSize(offsetWidth > 0 ? offsetWidth : rect.width, MIN_SIZE_PX);
9448
+ const startHeight = clampSize(offsetHeight > 0 ? offsetHeight : rect.height, MIN_SIZE_PX);
9449
+ const { scaleX: rawScaleX, scaleY: rawScaleY } = getElementScale(selectedElement);
9450
+ const scaleX = Math.max(EPSILON, rawScaleX);
9451
+ const scaleY = Math.max(EPSILON, rawScaleY);
9452
+ const transactionId = `resize-${Date.now()}-${txCounterRef.current++}`;
9453
+ const state = {
9454
+ transactionId,
9455
+ handle,
9456
+ startClientX: e.clientX,
9457
+ startClientY: e.clientY,
9458
+ startWidth,
9459
+ startHeight,
9460
+ scaleX,
9461
+ scaleY,
9462
+ fillTargetWidth: computeFillRenderedWidth(selectedElement),
9463
+ fillLocked: detectSizingMode(selectedElement, "width") === "fill"
9464
+ };
9465
+ emitSizingChange({}, { transactionId: state.transactionId, phase: "start" });
9466
+ const onPointerMove = (moveEvent) => {
9467
+ const dx = (moveEvent.clientX - state.startClientX) / state.scaleX;
9468
+ const dy = (moveEvent.clientY - state.startClientY) / state.scaleY;
9469
+ const nextSize = isEdgeHandle(state.handle) ? computeEdgeSize({
9470
+ handle: state.handle,
9471
+ startWidth: state.startWidth,
9472
+ startHeight: state.startHeight,
9473
+ dx,
9474
+ dy,
9475
+ minSize: MIN_SIZE_PX
9476
+ }) : computeCornerProportionalSize({
9477
+ handle: state.handle,
9478
+ startWidth: state.startWidth,
9479
+ startHeight: state.startHeight,
9480
+ dx,
9481
+ dy,
9482
+ minSize: MIN_SIZE_PX
9483
+ });
9484
+ const nextWidth = Math.max(MIN_SIZE_PX, Math.round(nextSize.width));
9485
+ const nextHeight = Math.max(MIN_SIZE_PX, Math.round(nextSize.height));
9486
+ const changes = {};
9487
+ if (WIDTH_HANDLES.has(state.handle)) {
9488
+ if (state.fillTargetWidth !== null) {
9489
+ const distance = Math.abs(nextWidth - state.fillTargetWidth);
9490
+ if (state.fillLocked) {
9491
+ if (distance > SNAP_OUT_PX) {
9492
+ state.fillLocked = false;
9493
+ }
9494
+ } else if (distance <= SNAP_IN_PX) {
9495
+ state.fillLocked = true;
8915
9496
  }
8916
- } else if (distance <= SNAP_IN_PX) {
8917
- state.fillLocked = true;
9497
+ } else {
9498
+ state.fillLocked = false;
9499
+ }
9500
+ if (state.fillLocked) {
9501
+ const fillWidth = state.fillTargetWidth ?? nextWidth;
9502
+ changes.width = createSizingValue("fill", fillWidth);
9503
+ } else {
9504
+ changes.width = createSizingValue("fixed", nextWidth);
8918
9505
  }
8919
- } else {
8920
- state.fillLocked = false;
8921
9506
  }
8922
- if (state.fillLocked) {
8923
- const fillWidth = state.fillTargetWidth ?? nextWidth;
8924
- changes.width = createSizingValue("fill", fillWidth);
8925
- } else {
8926
- changes.width = createSizingValue("fixed", nextWidth);
9507
+ if (HEIGHT_HANDLES.has(state.handle)) {
9508
+ changes.height = createSizingValue("fixed", nextHeight);
8927
9509
  }
8928
- }
8929
- if (HEIGHT_HANDLES.has(state.handle)) {
8930
- changes.height = createSizingValue("fixed", nextHeight);
8931
- }
8932
- if (Object.keys(changes).length === 0) return;
8933
- emitSizingChange(changes, { transactionId: state.transactionId, phase: "update" });
9510
+ if (Object.keys(changes).length === 0) return;
9511
+ emitSizingChange(changes, { transactionId: state.transactionId, phase: "update" });
9512
+ };
9513
+ const stop = () => {
9514
+ window.removeEventListener("pointermove", onPointerMove);
9515
+ window.removeEventListener("pointerup", stop);
9516
+ window.removeEventListener("pointercancel", stop);
9517
+ window.removeEventListener("blur", stop);
9518
+ cleanupRef.current = null;
9519
+ emitSizingChange({}, { transactionId: state.transactionId, phase: "end" });
9520
+ };
9521
+ cleanupRef.current = stop;
9522
+ window.addEventListener("pointermove", onPointerMove);
9523
+ window.addEventListener("pointerup", stop);
9524
+ window.addEventListener("pointercancel", stop);
9525
+ window.addEventListener("blur", stop);
8934
9526
  };
8935
- const stop = () => {
8936
- window.removeEventListener("pointermove", onPointerMove);
8937
- window.removeEventListener("pointerup", stop);
8938
- window.removeEventListener("pointercancel", stop);
8939
- window.removeEventListener("blur", stop);
8940
- cleanupRef.current = null;
8941
- emitSizingChange({}, { transactionId: state.transactionId, phase: "end" });
9527
+ },
9528
+ [emitSizingChange, enabled, onResizeSizingChange, selectedElement]
9529
+ );
9530
+ const getResizeHandleDoubleClick = React18.useCallback(
9531
+ (handle) => {
9532
+ return (e) => {
9533
+ if (!enabled || !onResizeSizingChange) return;
9534
+ if (!isEdgeHandle(handle)) return;
9535
+ const hasElementChildren = selectedElement.children.length > 0;
9536
+ const hasTextContent = Boolean(selectedElement.textContent?.trim());
9537
+ const isEligibleElement = hasElementChildren || hasTextContent;
9538
+ if (!isEligibleElement) return;
9539
+ e.preventDefault();
9540
+ e.stopPropagation();
9541
+ const rect = selectedElement.getBoundingClientRect();
9542
+ const width = Math.max(MIN_SIZE_PX, Math.round(rect.width));
9543
+ const height = Math.max(MIN_SIZE_PX, Math.round(rect.height));
9544
+ if (handle === "left" || handle === "right") {
9545
+ emitSizingChange({ width: createSizingValue("fit", width) });
9546
+ } else {
9547
+ emitSizingChange({ height: createSizingValue("fit", height) });
9548
+ }
8942
9549
  };
8943
- cleanupRef.current = stop;
8944
- window.addEventListener("pointermove", onPointerMove);
8945
- window.addEventListener("pointerup", stop);
8946
- window.addEventListener("pointercancel", stop);
8947
- window.addEventListener("blur", stop);
8948
- };
8949
- }, [emitSizingChange, enabled, onResizeSizingChange, selectedElement]);
8950
- const getResizeHandleDoubleClick = React18.useCallback((handle) => {
8951
- return (e) => {
8952
- if (!enabled || !onResizeSizingChange) return;
8953
- if (!isEdgeHandle(handle)) return;
8954
- const hasElementChildren = selectedElement.children.length > 0;
8955
- const hasTextContent = Boolean(selectedElement.textContent?.trim());
8956
- const isEligibleElement = hasElementChildren || hasTextContent;
8957
- if (!isEligibleElement) return;
8958
- e.preventDefault();
8959
- e.stopPropagation();
8960
- const rect = selectedElement.getBoundingClientRect();
8961
- const width = Math.max(MIN_SIZE_PX, Math.round(rect.width));
8962
- const height = Math.max(MIN_SIZE_PX, Math.round(rect.height));
8963
- if (handle === "left" || handle === "right") {
8964
- emitSizingChange({ width: createSizingValue("fit", width) });
8965
- } else {
8966
- emitSizingChange({ height: createSizingValue("fit", height) });
8967
- }
8968
- };
8969
- }, [emitSizingChange, enabled, onResizeSizingChange, selectedElement]);
9550
+ },
9551
+ [emitSizingChange, enabled, onResizeSizingChange, selectedElement]
9552
+ );
8970
9553
  return {
8971
9554
  getResizeHandlePointerDown,
8972
9555
  getResizeHandleDoubleClick
@@ -9591,17 +10174,20 @@ function getGroupBounds(rects) {
9591
10174
  if (rects.length === 0) {
9592
10175
  return { left: 0, top: 0, right: 0, bottom: 0 };
9593
10176
  }
9594
- return rects.reduce((bounds, rect) => ({
9595
- left: Math.min(bounds.left, rect.left),
9596
- top: Math.min(bounds.top, rect.top),
9597
- right: Math.max(bounds.right, rect.right),
9598
- bottom: Math.max(bounds.bottom, rect.bottom)
9599
- }), {
9600
- left: rects[0].left,
9601
- top: rects[0].top,
9602
- right: rects[0].right,
9603
- bottom: rects[0].bottom
9604
- });
10177
+ return rects.reduce(
10178
+ (bounds, rect) => ({
10179
+ left: Math.min(bounds.left, rect.left),
10180
+ top: Math.min(bounds.top, rect.top),
10181
+ right: Math.max(bounds.right, rect.right),
10182
+ bottom: Math.max(bounds.bottom, rect.bottom)
10183
+ }),
10184
+ {
10185
+ left: rects[0].left,
10186
+ top: rects[0].top,
10187
+ right: rects[0].right,
10188
+ bottom: rects[0].bottom
10189
+ }
10190
+ );
9605
10191
  }
9606
10192
  function MultiSelectionOverlay({ selectedElements }) {
9607
10193
  const elements = React20.useMemo(
@@ -9610,10 +10196,12 @@ function MultiSelectionOverlay({ selectedElements }) {
9610
10196
  );
9611
10197
  const [selectionRects, setSelectionRects] = React20.useState([]);
9612
10198
  const updateRects = React20.useCallback(() => {
9613
- setSelectionRects(elements.map((element) => ({
9614
- element,
9615
- rect: element.getBoundingClientRect()
9616
- })));
10199
+ setSelectionRects(
10200
+ elements.map((element) => ({
10201
+ element,
10202
+ rect: element.getBoundingClientRect()
10203
+ }))
10204
+ );
9617
10205
  }, [elements]);
9618
10206
  React20.useLayoutEffect(() => {
9619
10207
  updateRects();
@@ -11968,6 +12556,7 @@ function PanelFooter({
11968
12556
  onExportEdits,
11969
12557
  onSendToAgent,
11970
12558
  showSendButton = true,
12559
+ sendFailureReason,
11971
12560
  onPointerDown,
11972
12561
  onPointerMove,
11973
12562
  onPointerUp,
@@ -11976,6 +12565,13 @@ function PanelFooter({
11976
12565
  const [copied, setCopied] = React30.useState(false);
11977
12566
  const [copyError, setCopyError] = React30.useState(false);
11978
12567
  const [sendStatus, setSendStatus] = React30.useState("idle");
12568
+ const prevCanTriggerSendRef = React30.useRef(canTriggerSend);
12569
+ React30.useEffect(() => {
12570
+ if (prevCanTriggerSendRef.current !== canTriggerSend) {
12571
+ prevCanTriggerSendRef.current = canTriggerSend;
12572
+ setSendStatus("idle");
12573
+ }
12574
+ }, [canTriggerSend]);
11979
12575
  const handleCopy = async () => {
11980
12576
  if (!onExportEdits) return;
11981
12577
  const success = await onExportEdits();
@@ -11989,6 +12585,7 @@ function PanelFooter({
11989
12585
  setCopyError(true);
11990
12586
  setTimeout(() => setCopyError(false), 2e3);
11991
12587
  };
12588
+ const sendTooltipLabel = sendStatus === "offline" ? sendFailureReason === "unreachable" ? "Agent unreachable \u2014 click to retry" : "Agent rejected the edit \u2014 click to retry" : "Apply changes via agent";
11992
12589
  const handleSendToAgent = async () => {
11993
12590
  if (!onSendToAgent || sendStatus === "sending") return;
11994
12591
  setSendStatus("sending");
@@ -11998,7 +12595,6 @@ function PanelFooter({
11998
12595
  setTimeout(() => setSendStatus("idle"), 2e3);
11999
12596
  } else {
12000
12597
  setSendStatus("offline");
12001
- setTimeout(() => setSendStatus("idle"), 2e3);
12002
12598
  }
12003
12599
  };
12004
12600
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
@@ -12026,7 +12622,7 @@ function PanelFooter({
12026
12622
  children: copyError ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.X, { className: "text-red-500" }) : copied ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Check, { className: "text-green-500" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Copy, {})
12027
12623
  }
12028
12624
  ) }),
12029
- showSendButton && onSendToAgent && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: !canTriggerSend || sendStatus === "sending" ? "cursor-not-allowed" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tip, { label: "Apply changes via agent", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12625
+ showSendButton && onSendToAgent && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: !canTriggerSend || sendStatus === "sending" ? "cursor-not-allowed" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tip, { label: sendTooltipLabel, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12030
12626
  Button,
12031
12627
  {
12032
12628
  variant: "outline",
@@ -12721,6 +13317,7 @@ function DirectEditPanelInner({
12721
13317
  onSendToAgent,
12722
13318
  canSendToAgent = false,
12723
13319
  showSendButton = true,
13320
+ sendFailureReason,
12724
13321
  className,
12725
13322
  style,
12726
13323
  panelRef,
@@ -12783,89 +13380,91 @@ function DirectEditPanelInner({
12783
13380
  sectionRefs
12784
13381
  }
12785
13382
  ),
12786
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, onWheelCapture: (e) => e.stopPropagation(), children: [
12787
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12788
- LayoutSection,
12789
- {
12790
- elementInfo,
12791
- computedFlex,
12792
- computedSpacing,
12793
- computedSizing,
12794
- onToggleFlex,
12795
- onUpdateFlex,
12796
- onUpdateSpacing,
12797
- onUpdateSizing,
12798
- sectionRef: sectionRefs.layout
12799
- }
12800
- ),
12801
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.radius, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Radius", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12802
- BorderRadiusInputs,
12803
- {
12804
- values: {
12805
- topLeft: computedBorderRadius.borderTopLeftRadius,
12806
- topRight: computedBorderRadius.borderTopRightRadius,
12807
- bottomRight: computedBorderRadius.borderBottomRightRadius,
12808
- bottomLeft: computedBorderRadius.borderBottomLeftRadius
12809
- },
12810
- onChange: onUpdateBorderRadius
12811
- }
12812
- ) }) }),
12813
- computedColor && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.fill, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12814
- BackgroundFillSection,
12815
- {
12816
- backgroundColor: computedColor.backgroundColor,
12817
- onSetCSS,
12818
- pendingStyles
12819
- }
12820
- ) }),
12821
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.border, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12822
- BorderSection,
12823
- {
12824
- border: computedBorder,
12825
- borderColor: computedColor?.borderColor,
12826
- outlineColor: computedColor?.outlineColor,
12827
- borderStyleControlPreference,
12828
- onChange: onUpdateBorder,
12829
- onBatchChange: onBatchUpdateBorder,
12830
- onBorderColorChange: (value) => onUpdateColor("borderColor", value),
12831
- onOutlineColorChange: (value) => onUpdateColor("outlineColor", value),
12832
- onSetCSS,
12833
- pendingStyles
12834
- }
12835
- ) }),
12836
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.shadow, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12837
- ShadowSection,
12838
- {
12839
- boxShadow: computedBoxShadow,
12840
- onSetCSS,
12841
- pendingStyles
12842
- }
12843
- ) }),
12844
- elementInfo.isTextElement && computedTypography && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.text, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Text", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12845
- TypographyInputs,
12846
- {
12847
- typography: computedTypography,
12848
- onUpdate: onUpdateTypography
12849
- }
12850
- ) }) }),
12851
- computedColor && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.colors, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Selection colors", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12852
- FillSection,
12853
- {
12854
- textColor: computedColor.color,
12855
- borderColor: computedColor.borderColor,
12856
- outlineColor: computedColor.outlineColor,
12857
- selectionColors,
12858
- onTextChange: (value) => onUpdateColor("color", value),
12859
- onBorderColorChange: (value) => onUpdateColor("borderColor", value),
12860
- onOutlineColorChange: (value) => onUpdateColor("outlineColor", value),
12861
- onSelectionColorChange: onReplaceSelectionColor,
12862
- onSelectionColorTarget: onSelectSelectionColorTarget,
12863
- hasTextContent: elementInfo.isTextElement,
12864
- showBorderColor: computedColor.borderColor.alpha > 0,
12865
- showOutlineColor: computedColor.outlineColor.alpha > 0
12866
- }
12867
- ) }) })
12868
- ] }),
13383
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
13384
+ "div",
13385
+ {
13386
+ className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85",
13387
+ ref: scrollRef,
13388
+ onWheelCapture: (e) => e.stopPropagation(),
13389
+ children: [
13390
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13391
+ LayoutSection,
13392
+ {
13393
+ elementInfo,
13394
+ computedFlex,
13395
+ computedSpacing,
13396
+ computedSizing,
13397
+ onToggleFlex,
13398
+ onUpdateFlex,
13399
+ onUpdateSpacing,
13400
+ onUpdateSizing,
13401
+ sectionRef: sectionRefs.layout
13402
+ }
13403
+ ),
13404
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.radius, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Radius", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13405
+ BorderRadiusInputs,
13406
+ {
13407
+ values: {
13408
+ topLeft: computedBorderRadius.borderTopLeftRadius,
13409
+ topRight: computedBorderRadius.borderTopRightRadius,
13410
+ bottomRight: computedBorderRadius.borderBottomRightRadius,
13411
+ bottomLeft: computedBorderRadius.borderBottomLeftRadius
13412
+ },
13413
+ onChange: onUpdateBorderRadius
13414
+ }
13415
+ ) }) }),
13416
+ computedColor && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.fill, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13417
+ BackgroundFillSection,
13418
+ {
13419
+ backgroundColor: computedColor.backgroundColor,
13420
+ onSetCSS,
13421
+ pendingStyles
13422
+ }
13423
+ ) }),
13424
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.border, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13425
+ BorderSection,
13426
+ {
13427
+ border: computedBorder,
13428
+ borderColor: computedColor?.borderColor,
13429
+ outlineColor: computedColor?.outlineColor,
13430
+ borderStyleControlPreference,
13431
+ onChange: onUpdateBorder,
13432
+ onBatchChange: onBatchUpdateBorder,
13433
+ onBorderColorChange: (value) => onUpdateColor("borderColor", value),
13434
+ onOutlineColorChange: (value) => onUpdateColor("outlineColor", value),
13435
+ onSetCSS,
13436
+ pendingStyles
13437
+ }
13438
+ ) }),
13439
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.shadow, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13440
+ ShadowSection,
13441
+ {
13442
+ boxShadow: computedBoxShadow,
13443
+ onSetCSS,
13444
+ pendingStyles
13445
+ }
13446
+ ) }),
13447
+ elementInfo.isTextElement && computedTypography && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.text, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Text", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TypographyInputs, { typography: computedTypography, onUpdate: onUpdateTypography }) }) }),
13448
+ computedColor && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { ref: sectionRefs.colors, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CollapsibleSection, { title: "Selection colors", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13449
+ FillSection,
13450
+ {
13451
+ textColor: computedColor.color,
13452
+ borderColor: computedColor.borderColor,
13453
+ outlineColor: computedColor.outlineColor,
13454
+ selectionColors,
13455
+ onTextChange: (value) => onUpdateColor("color", value),
13456
+ onBorderColorChange: (value) => onUpdateColor("borderColor", value),
13457
+ onOutlineColorChange: (value) => onUpdateColor("outlineColor", value),
13458
+ onSelectionColorChange: onReplaceSelectionColor,
13459
+ onSelectionColorTarget: onSelectSelectionColorTarget,
13460
+ hasTextContent: elementInfo.isTextElement,
13461
+ showBorderColor: computedColor.borderColor.alpha > 0,
13462
+ showOutlineColor: computedColor.outlineColor.alpha > 0
13463
+ }
13464
+ ) }) })
13465
+ ]
13466
+ }
13467
+ ),
12869
13468
  (onExportEdits || showSendButton && onSendToAgent) && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12870
13469
  PanelFooter,
12871
13470
  {
@@ -12874,6 +13473,7 @@ function DirectEditPanelInner({
12874
13473
  onExportEdits,
12875
13474
  onSendToAgent,
12876
13475
  showSendButton,
13476
+ sendFailureReason,
12877
13477
  onPointerDown: onHeaderPointerDown,
12878
13478
  onPointerMove: onHeaderPointerMove,
12879
13479
  onPointerUp: onHeaderPointerUp,
@@ -12908,7 +13508,8 @@ function DirectEditPanelContent() {
12908
13508
  comments,
12909
13509
  activeCommentId,
12910
13510
  textEditingElement,
12911
- agentAvailable
13511
+ agentAvailable,
13512
+ lastSendFailure
12912
13513
  } = useDirectEditState();
12913
13514
  const {
12914
13515
  selectParent,
@@ -12936,11 +13537,15 @@ function DirectEditPanelContent() {
12936
13537
  addCommentReply,
12937
13538
  deleteComment,
12938
13539
  exportComment,
13540
+ exportEdits,
13541
+ sendEditToAgent: sendEditToAgent2,
12939
13542
  sendCommentToAgent: sendCommentToAgent2,
12940
13543
  setActiveCommentId,
12941
13544
  startTextEditing,
12942
13545
  toggleEditMode,
12943
- deleteSelection
13546
+ deleteSelection,
13547
+ setCommentDraftText,
13548
+ setCommentDraftBlockedHandler
12944
13549
  } = useDirectEditActions();
12945
13550
  const {
12946
13551
  position,
@@ -12962,46 +13567,67 @@ function DirectEditPanelContent() {
12962
13567
  });
12963
13568
  React34.useEffect(() => {
12964
13569
  commentDraftRef.current = "";
12965
- }, [activeCommentId]);
13570
+ setCommentDraftText("");
13571
+ }, [activeCommentId, setCommentDraftText]);
12966
13572
  const activeDraftComment = React34.useMemo(() => {
12967
13573
  if (!commentTargetElement || !activeCommentId) return null;
12968
13574
  const active = comments.find((comment) => comment.id === activeCommentId);
12969
- if (!active || active.text.trim().length > 0 || active.element !== commentTargetElement) return null;
13575
+ if (!active || active.text.trim().length > 0 || active.element !== commentTargetElement)
13576
+ return null;
12970
13577
  return active;
12971
13578
  }, [activeCommentId, commentTargetElement, comments]);
12972
- const { isActive: measurementActive, hoveredElement, measurements, mousePosition } = useMeasurement(
12973
- isOpen ? selectedElement : null
12974
- );
12975
13579
  const {
12976
- dragState,
12977
- dropIndicator,
12978
- startDrag
12979
- } = useMove({
13580
+ isActive: measurementActive,
13581
+ hoveredElement,
13582
+ measurements,
13583
+ mousePosition
13584
+ } = useMeasurement(isOpen ? selectedElement : null);
13585
+ const { dragState, dropIndicator, startDrag } = useMove({
12980
13586
  onMoveComplete: handleMoveComplete
12981
13587
  });
12982
13588
  const triggerCommentInputAttention = React34.useCallback((commentId) => {
12983
- setCommentInputAttention((prev) => prev?.commentId === commentId ? { commentId, nonce: prev.nonce + 1 } : { commentId, nonce: 1 });
13589
+ setCommentInputAttention(
13590
+ (prev) => prev?.commentId === commentId ? { commentId, nonce: prev.nonce + 1 } : { commentId, nonce: 1 }
13591
+ );
12984
13592
  }, []);
12985
- const hasPendingCommentDraft = React34.useCallback((nextCommentId = null) => {
12986
- if (!activeCommentId) return false;
12987
- if (nextCommentId && nextCommentId === activeCommentId) return false;
12988
- const active = comments.find((comment) => comment.id === activeCommentId);
12989
- if (!active) return false;
12990
- const hasUnsentDraft = active.text.trim().length === 0 && commentDraftRef.current.trim().length > 0;
12991
- if (!hasUnsentDraft) return false;
12992
- triggerCommentInputAttention(active.id);
12993
- return true;
12994
- }, [activeCommentId, comments, triggerCommentInputAttention]);
12995
- const handleSetActiveComment = React34.useCallback((id) => {
12996
- if (hasPendingCommentDraft(id)) return;
12997
- if (activeCommentId && activeCommentId !== id) {
13593
+ React34.useEffect(() => {
13594
+ if (!activeCommentId) {
13595
+ setCommentDraftBlockedHandler(null);
13596
+ return;
13597
+ }
13598
+ setCommentDraftBlockedHandler(() => {
13599
+ triggerCommentInputAttention(activeCommentId);
13600
+ });
13601
+ return () => {
13602
+ setCommentDraftBlockedHandler(null);
13603
+ };
13604
+ }, [activeCommentId, setCommentDraftBlockedHandler, triggerCommentInputAttention]);
13605
+ const hasPendingCommentDraft = React34.useCallback(
13606
+ (nextCommentId = null) => {
13607
+ if (!activeCommentId) return false;
13608
+ if (nextCommentId && nextCommentId === activeCommentId) return false;
12998
13609
  const active = comments.find((comment) => comment.id === activeCommentId);
12999
- if (active && active.text.trim().length === 0) {
13000
- deleteComment(active.id);
13610
+ if (!active) return false;
13611
+ const hasUnsentDraft = active.text.trim().length === 0 && commentDraftRef.current.trim().length > 0;
13612
+ if (!hasUnsentDraft) return false;
13613
+ triggerCommentInputAttention(active.id);
13614
+ return true;
13615
+ },
13616
+ [activeCommentId, comments, triggerCommentInputAttention]
13617
+ );
13618
+ const handleSetActiveComment = React34.useCallback(
13619
+ (id) => {
13620
+ if (hasPendingCommentDraft(id)) return;
13621
+ if (activeCommentId && activeCommentId !== id) {
13622
+ const active = comments.find((comment) => comment.id === activeCommentId);
13623
+ if (active && active.text.trim().length === 0) {
13624
+ deleteComment(active.id);
13625
+ }
13001
13626
  }
13002
- }
13003
- setActiveCommentId(id);
13004
- }, [activeCommentId, comments, hasPendingCommentDraft, deleteComment, setActiveCommentId]);
13627
+ setActiveCommentId(id);
13628
+ },
13629
+ [activeCommentId, comments, hasPendingCommentDraft, deleteComment, setActiveCommentId]
13630
+ );
13005
13631
  const handleCommentPillClick = React34.useCallback(() => {
13006
13632
  if (activeDraftComment) {
13007
13633
  handleSetActiveComment(null);
@@ -13009,13 +13635,23 @@ function DirectEditPanelContent() {
13009
13635
  }
13010
13636
  if (hasPendingCommentDraft()) return;
13011
13637
  if (!commentTargetElement) return;
13012
- const existingDraft = comments.find((comment) => comment.element === commentTargetElement && comment.text.trim().length === 0);
13638
+ const existingDraft = comments.find(
13639
+ (comment) => comment.element === commentTargetElement && comment.text.trim().length === 0
13640
+ );
13013
13641
  if (existingDraft) {
13014
13642
  setActiveCommentId(existingDraft.id);
13015
13643
  return;
13016
13644
  }
13017
13645
  addComment(commentTargetElement, getElementCommentAnchor(commentTargetElement));
13018
- }, [activeDraftComment, handleSetActiveComment, hasPendingCommentDraft, commentTargetElement, comments, setActiveCommentId, addComment]);
13646
+ }, [
13647
+ activeDraftComment,
13648
+ handleSetActiveComment,
13649
+ hasPendingCommentDraft,
13650
+ commentTargetElement,
13651
+ comments,
13652
+ setActiveCommentId,
13653
+ addComment
13654
+ ]);
13019
13655
  React34.useEffect(() => {
13020
13656
  const previous = previousCommentTriggerRef.current;
13021
13657
  previousCommentTriggerRef.current = { editModeActive, commentTargetElement };
@@ -13091,6 +13727,7 @@ function DirectEditPanelContent() {
13091
13727
  comment: activeDraftComment,
13092
13728
  attentionNonce: commentInputAttention?.commentId === activeDraftComment.id ? commentInputAttention.nonce : 0,
13093
13729
  draftRef: commentDraftRef,
13730
+ onDraftTextChange: setCommentDraftText,
13094
13731
  onSubmit: (text) => submitCommentDraft(activeDraftComment.id, text),
13095
13732
  onCancel: () => handleSetActiveComment(null)
13096
13733
  }
@@ -13111,58 +13748,81 @@ function DirectEditPanelContent() {
13111
13748
  if (pageTitle.length > 0) return pageTitle;
13112
13749
  return getElementDisplayName(pageFrameElement);
13113
13750
  }, [pageFrameElement]);
13114
- const handleSelectSelectionColorTarget = React34.useCallback((targetColor) => {
13115
- if (!selectedElement) return;
13116
- const toKey = (color) => `${color.hex.toUpperCase()}:${Math.round(color.alpha)}`;
13117
- const targetKey = toKey(targetColor);
13118
- const hasOwnText2 = (node) => Array.from(node.childNodes).some((child) => child.nodeType === Node.TEXT_NODE && (child.textContent ?? "").trim().length > 0);
13119
- const parseVisibleColor3 = (raw, fallbackCurrentColor) => {
13120
- const trimmed = raw.trim();
13121
- if (!trimmed || trimmed === "none" || trimmed === "transparent") return null;
13122
- const resolved = trimmed.toLowerCase() === "currentcolor" ? fallbackCurrentColor ?? trimmed : trimmed;
13123
- const parsed = parseColorValue(resolved);
13124
- return parsed.alpha > 0 ? parsed : null;
13125
- };
13126
- const hasMatchingColor = (node) => {
13127
- const computed = window.getComputedStyle(node);
13128
- const currentTextColor = computed.color;
13129
- const matches = (raw, fallback) => {
13130
- const parsed = parseVisibleColor3(raw, fallback);
13131
- return Boolean(parsed && toKey(parsed) === targetKey);
13751
+ const handleSelectSelectionColorTarget = React34.useCallback(
13752
+ (targetColor) => {
13753
+ if (!selectedElement) return;
13754
+ const toKey = (color) => `${color.hex.toUpperCase()}:${Math.round(color.alpha)}`;
13755
+ const targetKey = toKey(targetColor);
13756
+ const hasOwnText2 = (node) => Array.from(node.childNodes).some(
13757
+ (child) => child.nodeType === Node.TEXT_NODE && (child.textContent ?? "").trim().length > 0
13758
+ );
13759
+ const parseVisibleColor3 = (raw, fallbackCurrentColor) => {
13760
+ const trimmed = raw.trim();
13761
+ if (!trimmed || trimmed === "none" || trimmed === "transparent") return null;
13762
+ const resolved = trimmed.toLowerCase() === "currentcolor" ? fallbackCurrentColor ?? trimmed : trimmed;
13763
+ const parsed = parseColorValue(resolved);
13764
+ return parsed.alpha > 0 ? parsed : null;
13132
13765
  };
13133
- if (matches(computed.backgroundColor)) return true;
13134
- if (hasOwnText2(node) && matches(currentTextColor)) return true;
13135
- const borderSides = [
13136
- { style: computed.borderTopStyle, width: computed.borderTopWidth, color: computed.borderTopColor },
13137
- { style: computed.borderRightStyle, width: computed.borderRightWidth, color: computed.borderRightColor },
13138
- { style: computed.borderBottomStyle, width: computed.borderBottomWidth, color: computed.borderBottomColor },
13139
- { style: computed.borderLeftStyle, width: computed.borderLeftWidth, color: computed.borderLeftColor }
13140
- ];
13141
- for (const side of borderSides) {
13142
- if (side.style !== "none" && parseFloat(side.width) > 0 && matches(side.color, currentTextColor)) {
13766
+ const hasMatchingColor = (node) => {
13767
+ const computed = window.getComputedStyle(node);
13768
+ const currentTextColor = computed.color;
13769
+ const matches = (raw, fallback) => {
13770
+ const parsed = parseVisibleColor3(raw, fallback);
13771
+ return Boolean(parsed && toKey(parsed) === targetKey);
13772
+ };
13773
+ if (matches(computed.backgroundColor)) return true;
13774
+ if (hasOwnText2(node) && matches(currentTextColor)) return true;
13775
+ const borderSides = [
13776
+ {
13777
+ style: computed.borderTopStyle,
13778
+ width: computed.borderTopWidth,
13779
+ color: computed.borderTopColor
13780
+ },
13781
+ {
13782
+ style: computed.borderRightStyle,
13783
+ width: computed.borderRightWidth,
13784
+ color: computed.borderRightColor
13785
+ },
13786
+ {
13787
+ style: computed.borderBottomStyle,
13788
+ width: computed.borderBottomWidth,
13789
+ color: computed.borderBottomColor
13790
+ },
13791
+ {
13792
+ style: computed.borderLeftStyle,
13793
+ width: computed.borderLeftWidth,
13794
+ color: computed.borderLeftColor
13795
+ }
13796
+ ];
13797
+ for (const side of borderSides) {
13798
+ if (side.style !== "none" && parseFloat(side.width) > 0 && matches(side.color, currentTextColor)) {
13799
+ return true;
13800
+ }
13801
+ }
13802
+ if (computed.outlineStyle !== "none" && parseFloat(computed.outlineWidth) > 0 && matches(computed.outlineColor, currentTextColor)) {
13143
13803
  return true;
13144
13804
  }
13805
+ if (node instanceof SVGGraphicsElement) {
13806
+ const fillMatch = matches(computed.getPropertyValue("fill"), currentTextColor) || matches(node.getAttribute("fill") ?? "", currentTextColor);
13807
+ const strokeMatch = matches(computed.getPropertyValue("stroke"), currentTextColor) || matches(node.getAttribute("stroke") ?? "", currentTextColor);
13808
+ if (fillMatch || strokeMatch) return true;
13809
+ }
13810
+ return false;
13811
+ };
13812
+ const descendants = Array.from(selectedElement.querySelectorAll("*"));
13813
+ const firstDescendantMatch = descendants.find(
13814
+ (node) => node instanceof HTMLElement && hasMatchingColor(node)
13815
+ );
13816
+ if (firstDescendantMatch) {
13817
+ selectElement(firstDescendantMatch);
13818
+ return;
13145
13819
  }
13146
- if (computed.outlineStyle !== "none" && parseFloat(computed.outlineWidth) > 0 && matches(computed.outlineColor, currentTextColor)) {
13147
- return true;
13148
- }
13149
- if (node instanceof SVGGraphicsElement) {
13150
- const fillMatch = matches(computed.getPropertyValue("fill"), currentTextColor) || matches(node.getAttribute("fill") ?? "", currentTextColor);
13151
- const strokeMatch = matches(computed.getPropertyValue("stroke"), currentTextColor) || matches(node.getAttribute("stroke") ?? "", currentTextColor);
13152
- if (fillMatch || strokeMatch) return true;
13820
+ if (hasMatchingColor(selectedElement)) {
13821
+ selectElement(selectedElement);
13153
13822
  }
13154
- return false;
13155
- };
13156
- const descendants = Array.from(selectedElement.querySelectorAll("*"));
13157
- const firstDescendantMatch = descendants.find((node) => node instanceof HTMLElement && hasMatchingColor(node));
13158
- if (firstDescendantMatch) {
13159
- selectElement(firstDescendantMatch);
13160
- return;
13161
- }
13162
- if (hasMatchingColor(selectedElement)) {
13163
- selectElement(selectedElement);
13164
- }
13165
- }, [selectedElement, selectElement]);
13823
+ },
13824
+ [selectedElement, selectElement]
13825
+ );
13166
13826
  const handleMoveStart = (e, targetElement, options) => {
13167
13827
  const elementToDrag = targetElement ?? selectedElement;
13168
13828
  if (elementToDrag) {
@@ -13251,7 +13911,11 @@ function DirectEditPanelContent() {
13251
13911
  hoveredElement,
13252
13912
  measurements: [
13253
13913
  ...measurements,
13254
- ...calculateGuidelineMeasurements(selectedElement, getStoredGuidelines(), mousePosition)
13914
+ ...calculateGuidelineMeasurements(
13915
+ selectedElement,
13916
+ getStoredGuidelines(),
13917
+ mousePosition
13918
+ )
13255
13919
  ]
13256
13920
  }
13257
13921
  ),
@@ -13306,6 +13970,9 @@ function DirectEditPanelContent() {
13306
13970
  onSelectSelectionColorTarget: handleSelectSelectionColorTarget,
13307
13971
  onUpdateTypography: updateTypographyProperty,
13308
13972
  onReset: resetToOriginal,
13973
+ onExportEdits: exportEdits,
13974
+ onSendToAgent: agentAvailable ? sendEditToAgent2 : void 0,
13975
+ sendFailureReason: lastSendFailure?.reason ?? null,
13309
13976
  className: "fixed z-[99999]",
13310
13977
  style: {
13311
13978
  left: position.x,
@@ -14240,7 +14907,8 @@ function EditsPopover({
14240
14907
  onExportAllEdits,
14241
14908
  onClearSessionEdits,
14242
14909
  onRemoveSessionEdit,
14243
- onDeleteComment
14910
+ onDeleteComment,
14911
+ sendFailure
14244
14912
  }) {
14245
14913
  const [copied, setCopied] = React38.useState(false);
14246
14914
  const editsPopupRef = React38.useRef(null);
@@ -14253,6 +14921,7 @@ function EditsPopover({
14253
14921
  const visibleItems = React38.useMemo(() => {
14254
14922
  return editsSnapshot.filter((item) => {
14255
14923
  if (item.type === "comment") return true;
14924
+ if (item.edit.deleted) return true;
14256
14925
  if (!item.edit.move) return true;
14257
14926
  const moveIntent = getMoveIntentForEdit(item.edit, movePlanContext);
14258
14927
  const hasStyleOrText = Object.keys(item.edit.pendingStyles).length > 0 || item.edit.textEdit != null;
@@ -14357,12 +15026,15 @@ ${text}`);
14357
15026
  visibleItems.length === 0 && multiSelectContextItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "px-3 pb-3 pt-1 text-xs text-muted-foreground", children: "No edits or comments yet." }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "max-h-[240px] overflow-y-auto px-1 py-1", children: [
14358
15027
  visibleItems.map((item, i) => {
14359
15028
  const isEdit = item.type === "edit";
15029
+ const isDeleted = isEdit && Boolean(item.edit.deleted);
14360
15030
  const moveIntent = isEdit && item.edit.move ? getMoveIntentForEdit(item.edit, movePlanContext) : null;
14361
15031
  const isMoved = Boolean(moveIntent);
14362
15032
  const locator = isEdit ? item.edit.locator : item.comment.locator;
14363
15033
  const componentName = locator.reactStack[0]?.name ?? locator.tagName;
14364
15034
  let valueSummary = "";
14365
- if (isEdit) {
15035
+ if (isEdit && isDeleted) {
15036
+ valueSummary = locator.textPreview || locator.domSelector || locator.tagName;
15037
+ } else if (isEdit) {
14366
15038
  const entries = Object.entries(item.edit.pendingStyles);
14367
15039
  const editValues = [];
14368
15040
  for (const [prop, value] of entries) {
@@ -14383,6 +15055,7 @@ ${text}`);
14383
15055
  }
14384
15056
  valueSummary = commentValues.join(", ");
14385
15057
  }
15058
+ const failed = isEdit ? sendFailure?.failedEditElements.includes(item.edit.element) : sendFailure?.failedCommentIds.includes(item.comment.id);
14386
15059
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
14387
15060
  "div",
14388
15061
  {
@@ -14401,13 +15074,16 @@ ${text}`);
14401
15074
  },
14402
15075
  children: [
14403
15076
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col items-start gap-[4px]", children: [
14404
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Badge, { variant: "secondary", className: "h-6 shrink-0 px-1.5 text-xs", children: [
14405
- "@<",
14406
- componentName,
14407
- ">"
15077
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-1", children: [
15078
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Badge, { variant: "secondary", className: "h-6 shrink-0 px-1.5 text-xs", children: [
15079
+ "@<",
15080
+ componentName,
15081
+ ">"
15082
+ ] }),
15083
+ failed && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Badge, { variant: "default", className: "h-6 shrink-0 px-1.5 text-xs bg-red-500 text-white border-transparent", children: "Failed" })
14408
15084
  ] }),
14409
15085
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "min-w-0 max-w-full truncate text-xs text-muted-foreground", children: [
14410
- isEdit ? isMoved ? "moved: " : "edit: " : "comment: ",
15086
+ isEdit ? isDeleted ? "deleted: " : isMoved ? "moved: " : "edit: " : "comment: ",
14411
15087
  truncateText(valueSummary, 128)
14412
15088
  ] })
14413
15089
  ] }),
@@ -14659,6 +15335,7 @@ function SettingsPopover({
14659
15335
  { label: "Undo", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Command, { className: "size-2.5" }, "cmd"), "Z"] : ["Ctrl", "Z"] },
14660
15336
  { label: "Group selection", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Command, { className: "size-2.5" }, "cmd"), "G"] : ["Ctrl", "G"] },
14661
15337
  { label: "Add frame", keys: ["F"] },
15338
+ { label: "Add text", keys: ["T"] },
14662
15339
  { label: "Add div", keys: ["D"] },
14663
15340
  { label: "Add to selection", keys: [/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ArrowBigUp, { className: "size-3" }, "shift"), "Click"] },
14664
15341
  { label: "Marquee select", keys: ["Drag"] },
@@ -14701,6 +15378,8 @@ function DirectEditToolbarInner({
14701
15378
  onExportAllEdits,
14702
15379
  onSendAllToAgents,
14703
15380
  agentAvailable = true,
15381
+ sendFailureReason,
15382
+ sendFailure,
14704
15383
  onClearSessionEdits,
14705
15384
  onRemoveSessionEdit,
14706
15385
  onDeleteComment,
@@ -14710,7 +15389,8 @@ function DirectEditToolbarInner({
14710
15389
  onToggleCanvas,
14711
15390
  onSetCanvasZoom,
14712
15391
  onZoomTo100,
14713
- onFitToViewport
15392
+ onFitToViewport,
15393
+ onInsertElement
14714
15394
  }) {
14715
15395
  const container = usePortalContainer();
14716
15396
  const toolbarRef = React40.useRef(null);
@@ -14719,7 +15399,8 @@ function DirectEditToolbarInner({
14719
15399
  const [activePopover, setActivePopover] = React40.useState(null);
14720
15400
  const [applyStatus, setApplyStatus] = React40.useState("idle");
14721
15401
  const applyTimerRef = React40.useRef(null);
14722
- const showApplyButton = agentAvailable && Boolean(onSendAllToAgents);
15402
+ const showApplyButton = (agentAvailable || applyStatus !== "idle") && Boolean(onSendAllToAgents);
15403
+ const showInsertButtons = Boolean(onInsertElement);
14723
15404
  const totalItemCount = sessionEditCount + multiSelectCount;
14724
15405
  const sizeCacheRef = React40.useRef({});
14725
15406
  React40.useEffect(() => {
@@ -14773,6 +15454,16 @@ function DirectEditToolbarInner({
14773
15454
  setApplyStatus("idle");
14774
15455
  }, 2e3);
14775
15456
  }, []);
15457
+ const prevTotalItemCountRef = React40.useRef(totalItemCount);
15458
+ React40.useEffect(() => {
15459
+ if (prevTotalItemCountRef.current !== totalItemCount) {
15460
+ prevTotalItemCountRef.current = totalItemCount;
15461
+ if (applyStatus === "offline") {
15462
+ setApplyStatus("idle");
15463
+ }
15464
+ }
15465
+ }, [totalItemCount, applyStatus]);
15466
+ const applyTooltipLabel = applyStatus === "offline" ? sendFailureReason === "unreachable" ? "Agent unreachable \u2014 click to retry" : "Agent rejected the edit \u2014 click to retry" : "Apply all changes via agent";
14776
15467
  const handleApplyAll = React40.useCallback(async () => {
14777
15468
  if (!onSendAllToAgents || totalItemCount === 0 || applyStatus === "sending") return;
14778
15469
  setApplyStatus("sending");
@@ -14782,8 +15473,12 @@ function DirectEditToolbarInner({
14782
15473
  } catch {
14783
15474
  success = false;
14784
15475
  }
14785
- setApplyStatus(success ? "sent" : "offline");
14786
- scheduleApplyReset();
15476
+ if (success) {
15477
+ setApplyStatus("sent");
15478
+ scheduleApplyReset();
15479
+ } else {
15480
+ setApplyStatus("offline");
15481
+ }
14787
15482
  }, [applyStatus, onSendAllToAgents, scheduleApplyReset, totalItemCount]);
14788
15483
  const dragHandlers = React40.useMemo(() => ({
14789
15484
  onPointerDown: handlePointerDown,
@@ -14864,6 +15559,38 @@ function DirectEditToolbarInner({
14864
15559
  },
14865
15560
  ...dragHandlers,
14866
15561
  children: [
15562
+ showInsertButtons && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
15563
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Tooltip, { children: [
15564
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15565
+ TooltipTrigger,
15566
+ {
15567
+ className: cn(toolbarBtnClass, "text-muted-foreground hover:bg-muted hover:text-foreground"),
15568
+ onPointerDown: (e) => e.stopPropagation(),
15569
+ onClick: () => onInsertElement?.("frame"),
15570
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react17.Square, { className: "size-4" })
15571
+ }
15572
+ ),
15573
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
15574
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: "Add frame" }),
15575
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("kbd", { className: kbdClass, children: "F" })
15576
+ ] })
15577
+ ] }),
15578
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Tooltip, { children: [
15579
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15580
+ TooltipTrigger,
15581
+ {
15582
+ className: cn(toolbarBtnClass, "text-muted-foreground hover:bg-muted hover:text-foreground"),
15583
+ onPointerDown: (e) => e.stopPropagation(),
15584
+ onClick: () => onInsertElement?.("text"),
15585
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react17.Type, { className: "size-4" })
15586
+ }
15587
+ ),
15588
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
15589
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: "Add text" }),
15590
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("kbd", { className: kbdClass, children: "T" })
15591
+ ] })
15592
+ ] })
15593
+ ] }),
14867
15594
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14868
15595
  EditsPopover,
14869
15596
  {
@@ -14876,7 +15603,8 @@ function DirectEditToolbarInner({
14876
15603
  onExportAllEdits,
14877
15604
  onClearSessionEdits,
14878
15605
  onRemoveSessionEdit,
14879
- onDeleteComment
15606
+ onDeleteComment,
15607
+ sendFailure
14880
15608
  }
14881
15609
  ),
14882
15610
  showApplyButton && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Tooltip, { children: [
@@ -14900,7 +15628,7 @@ function DirectEditToolbarInner({
14900
15628
  ]
14901
15629
  }
14902
15630
  ),
14903
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: "Apply all changes via agent" }) })
15631
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: applyTooltipLabel }) })
14904
15632
  ] }),
14905
15633
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14906
15634
  "div",
@@ -14962,7 +15690,7 @@ function DirectEditToolbarInner({
14962
15690
  return toolbar;
14963
15691
  }
14964
15692
  function DirectEditToolbarContent() {
14965
- const { editModeActive, theme, sessionEditCount, multiSelectContextCount, selectedElements, canvas, agentAvailable } = useDirectEditState();
15693
+ const { editModeActive, theme, sessionEditCount, multiSelectContextCount, selectedElements, canvas, agentAvailable, lastSendFailure } = useDirectEditState();
14966
15694
  const {
14967
15695
  toggleEditMode,
14968
15696
  setTheme,
@@ -14972,6 +15700,7 @@ function DirectEditToolbarContent() {
14972
15700
  clearSessionEdits,
14973
15701
  removeSessionEdit,
14974
15702
  deleteComment,
15703
+ insertElement,
14975
15704
  toggleCanvas,
14976
15705
  setCanvasZoom,
14977
15706
  zoomCanvasTo100,
@@ -14994,6 +15723,8 @@ function DirectEditToolbarContent() {
14994
15723
  onExportAllEdits: exportAllEdits,
14995
15724
  onSendAllToAgents: sendAllSessionItemsToAgent,
14996
15725
  agentAvailable,
15726
+ sendFailureReason: lastSendFailure?.reason ?? null,
15727
+ sendFailure: lastSendFailure,
14997
15728
  onClearSessionEdits: clearSessionEdits,
14998
15729
  onRemoveSessionEdit: removeSessionEdit,
14999
15730
  onDeleteComment: deleteComment,
@@ -15002,7 +15733,8 @@ function DirectEditToolbarContent() {
15002
15733
  onToggleCanvas: toggleCanvas,
15003
15734
  onSetCanvasZoom: setCanvasZoom,
15004
15735
  onZoomTo100: zoomCanvasTo100,
15005
- onFitToViewport: fitCanvasToViewport
15736
+ onFitToViewport: fitCanvasToViewport,
15737
+ onInsertElement: insertElement
15006
15738
  }
15007
15739
  );
15008
15740
  }