@json-to-office/jto 0.33.2 → 0.35.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/cli.js +214 -516
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/HomePage-DgVVosCp.js +106 -0
- package/dist/client/assets/HomePage-DgVVosCp.js.map +1 -0
- package/dist/client/assets/{JsonEditorPage-GZV7oJD2.js → JsonEditorPage-13oxEHfY.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-GZV7oJD2.js.map → JsonEditorPage-13oxEHfY.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-btNzJ41o.js → MonacoPluginProvider-DiUyU9px.js} +3 -3
- package/dist/client/assets/{MonacoPluginProvider-btNzJ41o.js.map → MonacoPluginProvider-DiUyU9px.js.map} +1 -1
- package/dist/client/assets/editor-monaco-json-CTrPZKuA.js +24 -0
- package/dist/client/assets/{editor-monaco-json-rhvIaBDI.js.map → editor-monaco-json-CTrPZKuA.js.map} +1 -1
- package/dist/client/assets/{editor-Cugq4RzH.js → editor-ouhvdGgK.js} +2 -2
- package/dist/client/assets/{editor-Cugq4RzH.js.map → editor-ouhvdGgK.js.map} +1 -1
- package/dist/client/assets/{editor-refs-store-DeJZ8FB9.js → editor-refs-store-DNQzN0_z.js} +2 -2
- package/dist/client/assets/{editor-refs-store-DeJZ8FB9.js.map → editor-refs-store-DNQzN0_z.js.map} +1 -1
- package/dist/client/assets/index-CRuLxurM.js +5 -0
- package/dist/client/assets/index-CRuLxurM.js.map +1 -0
- package/dist/client/assets/index-CnUTzeor.css +1 -0
- package/dist/client/assets/preview-D3QYaLPp.js +4 -0
- package/dist/client/assets/preview-D3QYaLPp.js.map +1 -0
- package/dist/client/assets/{ui-vendor-Cs3OXpi7.js → ui-vendor-DyQLnWB8.js} +16 -11
- package/dist/client/assets/ui-vendor-DyQLnWB8.js.map +1 -0
- package/dist/client/index.html +3 -3
- package/dist/client/templates/Alternative deck 16_9.pptx.json +91 -49
- package/dist/client/templates/Company deck 16_9.pptx.json +134 -70
- package/dist/client/templates/Company deck 4_3.pptx.json +84 -44
- package/dist/client/templates/data-report-presentation.pptx.json +100 -52
- package/dist/client/templates/modern-annual-report-1.docx.json +207 -116
- package/dist/client/templates/modern-annual-report-2.docx.json +52 -37
- package/dist/client/templates/modern-annual-report-3.docx.json +40 -20
- package/dist/client/templates/tech-report.docx.json +96 -48
- package/dist/render-server.js +168 -106
- package/dist/render-server.js.map +1 -1
- package/package.json +7 -8
- package/dist/client/assets/HomePage-Cq6woGMG.js +0 -106
- package/dist/client/assets/HomePage-Cq6woGMG.js.map +0 -1
- package/dist/client/assets/editor-monaco-json-rhvIaBDI.js +0 -24
- package/dist/client/assets/index-C9ply7vX.css +0 -1
- package/dist/client/assets/index-C9uVroFQ.js +0 -5
- package/dist/client/assets/index-C9uVroFQ.js.map +0 -1
- package/dist/client/assets/preview-B_B09gpA.js +0 -3
- package/dist/client/assets/preview-B_B09gpA.js.map +0 -1
- package/dist/client/assets/ui-vendor-Cs3OXpi7.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--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-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-cyrillic-ext-wght-normal.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-cyrillic-wght-normal.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-greek-ext-wght-normal.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-greek-wght-normal.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-vietnamese-wght-normal.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-latin-ext-wght-normal.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(./files/inter-latin-wght-normal.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@layer theme{:root,:host{--font-sans:"Inter Variable","Inter",system-ui,-apple-system,"Segoe UI",sans-serif;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-2xl:42rem;--container-4xl:56rem;--container-5xl:64rem;--text-xs:11px;--text-xs--line-height:16px;--text-sm:13px;--text-sm--line-height:18px;--text-base:14px;--text-base--line-height:20px;--text-lg:16px;--text-lg--line-height:24px;--text-2xl:24px;--text-2xl--line-height:30px;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-xl:10px;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:"Inter Variable","Inter",system-ui,-apple-system,"Segoe UI",sans-serif;--default-mono-font-family:ui-monospace,"SFMono-Regular","SF Mono","Menlo","Consolas",monospace;--animate-progress-indeterminate:progress-indeterminate 1.4s ease-in-out infinite}}@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%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,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}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance: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{--background:216 29% 97%;--foreground:225 28% 14%;--card:0 0% 100%;--card-foreground:225 28% 14%;--popover:0 0% 100%;--popover-foreground:225 28% 14%;--secondary:228 33% 98%;--secondary-foreground:225 28% 14%;--muted:228 33% 98%;--muted-foreground:218 30% 47%;--accent:228 33% 98%;--accent-foreground:225 28% 14%;--border:218 23% 91%;--input:218 23% 91%;--primary:229 24.8% 29.2%;--primary-foreground:0 0% 100%;--destructive:0 84.2% 60.2%;--destructive-foreground:0 0% 98%;--ring:223 92% 64%;--radius:.375rem;--warning:32 95% 44%;--warning-foreground:0 0% 100%;--warning-bg:48 96% 89%;--warning-bg-foreground:22 78% 26%;--success:142 72% 36%;--success-foreground:0 0% 100%;--success-bg:141 79% 93%;--success-bg-foreground:145 80% 17%;--destructive-bg:0 93% 94%;--destructive-bg-foreground:0 63% 31%;--header-bg:228 33% 98%;--accent2:28 80% 52%;--accent2-foreground:0 0% 100%;--data-blue:223 92% 64%;--data-blue-bg:214 95% 93%;--data-blue-bg-foreground:226 57% 21%;--chart-1:227 25% 15%;--chart-2:223 92% 64%;--chart-3:258 90% 66%;--chart-4:142 72% 36%;--chart-5:218 30% 47%;--sidebar:0 0% 100%;--sidebar-foreground:225 28% 14%;--sidebar-accent:220 20% 94%;--sidebar-accent-foreground:225 28% 14%;--sidebar-border:218 23% 91%;--sidebar-ring:223 92% 64%;--sidebar-primary:223 92% 64%;--sidebar-primary-foreground:0 0% 100%;--switch-off:220 24% 82%;--surface-editor:0 0% 100%;--surface-preview:216 29% 97%;--surface-chat:0 0% 100%}.dark{--background:227 24.7% 15.1%;--foreground:0 0% 98%;--card:228 22% 20%;--card-foreground:0 0% 98%;--popover:228 22% 25%;--popover-foreground:0 0% 98%;--secondary:228 18% 28%;--secondary-foreground:0 0% 98%;--muted:228 18% 28%;--muted-foreground:218 28% 72%;--accent:228 18% 28%;--accent-foreground:0 0% 98%;--border:228 16% 34%;--input:228 16% 34%;--primary:223 92% 75%;--primary-foreground:227 25% 12%;--destructive:0 93.5% 81.8%;--destructive-foreground:227 24.7% 15.1%;--ring:223 92% 72%;--warning:45 96% 74%;--warning-foreground:240 5.9% 10%;--warning-bg:26 55% 18%;--warning-bg-foreground:48 97% 77%;--success:158 64% 52%;--success-foreground:240 5.9% 10%;--success-bg:142 40% 16%;--success-bg-foreground:141 79% 85%;--destructive-bg:0 40% 18%;--destructive-bg-foreground:0 96% 89%;--header-bg:228 18% 28%;--accent2:28 85% 62%;--accent2-foreground:25 60% 12%;--data-blue:223 100% 74%;--data-blue-bg:226 45% 22%;--data-blue-bg-foreground:214 95% 87%;--sidebar:222 30% 9%;--sidebar-foreground:215 20% 82%;--sidebar-accent:229 22% 20%;--sidebar-accent-foreground:0 0% 100%;--sidebar-border:229 18% 22%;--sidebar-ring:223 92% 72%;--sidebar-primary:223 92% 75%;--sidebar-primary-foreground:227 25% 12%;--chart-1:229 51.1% 56.7%;--chart-2:223 92% 64%;--chart-3:258 90% 72%;--chart-4:160 84% 45%;--chart-5:215 20% 72%;--switch-off:228 14% 42%;--surface-editor:228 22% 20%;--surface-preview:227 24.7% 15.1%;--surface-chat:228 22% 20%}*,:after,:before,::backdrop{border-color:hsl(var(--border))}::file-selector-button{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground));font-family:var(--font-sans);font-feature-settings:"cv02","cv03","cv04","cv11";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}button:not(:disabled):not([aria-disabled=true]),[role=button]:not([aria-disabled=true]),[role=tab]:not([aria-disabled=true]),[role=switch]:not([aria-disabled=true]),[role=checkbox]:not([aria-disabled=true]),[role=radio]:not([aria-disabled=true]),[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio],[role=option],label:has(>button,>input[type=checkbox],>input[type=radio],>input[type=file]){cursor:pointer}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.inset-x-0{inset-inline:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.-top-1\.5{top:calc(var(--spacing)*-1.5)}.top-0{top:calc(var(--spacing)*0)}.top-1{top:calc(var(--spacing)*1)}.top-1\.5{top:calc(var(--spacing)*1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-3\.5{top:calc(var(--spacing)*3.5)}.top-4{top:calc(var(--spacing)*4)}.top-\[50\%\]{top:50%}.-right-1\.5{right:calc(var(--spacing)*-1.5)}.right-0{right:calc(var(--spacing)*0)}.right-1{right:calc(var(--spacing)*1)}.right-1\.5{right:calc(var(--spacing)*1.5)}.right-2{right:calc(var(--spacing)*2)}.right-2\.5{right:calc(var(--spacing)*2.5)}.right-3{right:calc(var(--spacing)*3)}.right-4{right:calc(var(--spacing)*4)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-1{bottom:calc(var(--spacing)*1)}.bottom-1\.5{bottom:calc(var(--spacing)*1.5)}.left-0{left:calc(var(--spacing)*0)}.left-2{left:calc(var(--spacing)*2)}.left-\[50\%\]{left:50%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-1{margin-inline:calc(var(--spacing)*1)}.mx-2{margin-inline:calc(var(--spacing)*2)}.mx-3{margin-inline:calc(var(--spacing)*3)}.mx-3\.5{margin-inline:calc(var(--spacing)*3.5)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-1\.5{margin-right:calc(var(--spacing)*1.5)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-5{margin-left:calc(var(--spacing)*5)}.ml-\[13px\]{margin-left:13px}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-1\.5{width:calc(var(--spacing)*1.5);height:calc(var(--spacing)*1.5)}.size-2\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-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-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.h-1{height:calc(var(--spacing)*1)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-20{height:calc(var(--spacing)*20)}.h-48{height:calc(var(--spacing)*48)}.h-64{height:calc(var(--spacing)*64)}.h-\[1\.2rem\]{height:1.2rem}.h-\[1\.15rem\]{height:1.15rem}.h-\[1px\]{height:1px}.h-\[18px\]{height:18px}.h-\[420px\]{height:420px}.h-\[600px\]{height:600px}.h-\[calc\(100\%-2\.5rem\)\]{height:calc(100% - 2.5rem)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.h-svh{height:100svh}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-80{max-height:calc(var(--spacing)*80)}.max-h-96{max-height:calc(var(--spacing)*96)}.max-h-\[45vh\]{max-height:45vh}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[300px\]{max-height:300px}.max-h-screen{max-height:100vh}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-8{min-height:calc(var(--spacing)*8)}.min-h-9{min-height:calc(var(--spacing)*9)}.min-h-\[36px\]{min-height:36px}.min-h-\[80px\]{min-height:80px}.min-h-\[200px\]{min-height:200px}.min-h-screen{min-height:100vh}.min-h-svh{min-height:100svh}.w-1\.5{width:calc(var(--spacing)*1.5)}.w-1\/2{width:50%}.w-2{width:calc(var(--spacing)*2)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-2\/5{width:40%}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-3\/4{width:75%}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-44{width:calc(var(--spacing)*44)}.w-52{width:calc(var(--spacing)*52)}.w-64{width:calc(var(--spacing)*64)}.w-72{width:calc(var(--spacing)*72)}.w-\[--sidebar-width\]{width:--sidebar-width}.w-\[1\.2rem\]{width:1.2rem}.w-\[1px\]{width:1px}.w-\[2px\]{width:2px}.w-\[140px\]{width:140px}.w-\[240px\]{width:240px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-\[--skeleton-width\]{max-width:--skeleton-width}.max-w-\[90\%\]{max-width:90%}.max-w-\[110px\]{max-width:110px}.max-w-\[120px\]{max-width:120px}.max-w-\[140px\]{max-width:140px}.max-w-\[160px\]{max-width:160px}.max-w-\[180px\]{max-width:180px}.max-w-\[200px\]{max-width:200px}.max-w-\[280px\]{max-width:280px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-4{min-width:calc(var(--spacing)*4)}.min-w-5{min-width:calc(var(--spacing)*5)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[12rem\]{min-width:12rem}.min-w-\[260px\]{min-width:260px}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-x-px{--tw-translate-x:-1px;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-px{--tw-translate-x:1px;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\[calc\(-50\%_-_2px\)\]{--tw-translate-y: calc(-50% - 2px) ;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-0{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-0{rotate:none}.rotate-45{rotate:45deg}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-progress-indeterminate{animation:var(--animate-progress-indeterminate)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-nowrap{flex-wrap:nowrap}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0{gap:calc(var(--spacing)*0)}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.gap-px{gap:1px}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*5)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-0\.5{column-gap:calc(var(--spacing)*.5)}.gap-x-1{column-gap:calc(var(--spacing)*1)}.gap-x-2{column-gap:calc(var(--spacing)*2)}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*1)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*4)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border\/50>:not(:last-child)){border-color:hsl(var(--border))}@supports (color:color-mix(in lab,red,red)){:where(.divide-border\/50>:not(:last-child)){border-color:color-mix(in oklab,hsl(var(--border))50%,transparent)}}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\[2px\]{border-radius:2px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-none{border-radius:0}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-t-md{border-top-left-radius:calc(var(--radius) - 2px);border-top-right-radius:calc(var(--radius) - 2px)}.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-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.border-border,.border-border\/40{border-color:hsl(var(--border))}@supports (color:color-mix(in lab,red,red)){.border-border\/40{border-color:color-mix(in oklab,hsl(var(--border))40%,transparent)}}.border-border\/60{border-color:hsl(var(--border))}@supports (color:color-mix(in lab,red,red)){.border-border\/60{border-color:color-mix(in oklab,hsl(var(--border))60%,transparent)}}.border-destructive,.border-destructive\/20{border-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.border-destructive\/20{border-color:color-mix(in oklab,hsl(var(--destructive))20%,transparent)}}.border-destructive\/30{border-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.border-destructive\/30{border-color:color-mix(in oklab,hsl(var(--destructive))30%,transparent)}}.border-foreground{border-color:hsl(var(--foreground))}.border-input{border-color:hsl(var(--input))}.border-muted-foreground,.border-muted-foreground\/40{border-color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.border-muted-foreground\/40{border-color:color-mix(in oklab,hsl(var(--muted-foreground))40%,transparent)}}.border-muted-foreground\/50{border-color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.border-muted-foreground\/50{border-color:color-mix(in oklab,hsl(var(--muted-foreground))50%,transparent)}}.border-primary{border-color:hsl(var(--primary))}.border-primary-foreground\/20{border-color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.border-primary-foreground\/20{border-color:color-mix(in oklab,hsl(var(--primary-foreground))20%,transparent)}}.border-primary\/20{border-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.border-primary\/20{border-color:color-mix(in oklab,hsl(var(--primary))20%,transparent)}}.border-secondary{border-color:hsl(var(--secondary))}.border-sidebar-border,.border-sidebar-border\/70{border-color:hsl(var(--sidebar-border))}@supports (color:color-mix(in lab,red,red)){.border-sidebar-border\/70{border-color:color-mix(in oklab,hsl(var(--sidebar-border))70%,transparent)}}.border-transparent{border-color:#0000}.border-t-transparent{border-top-color:#0000}.border-l-destructive{border-left-color:hsl(var(--destructive))}.border-l-transparent{border-left-color:#0000}.bg-accent{background-color:hsl(var(--accent))}.bg-accent2{background-color:hsl(var(--accent2))}.bg-background,.bg-background\/60{background-color:hsl(var(--background))}@supports (color:color-mix(in lab,red,red)){.bg-background\/60{background-color:color-mix(in oklab,hsl(var(--background))60%,transparent)}}.bg-background\/80{background-color:hsl(var(--background))}@supports (color:color-mix(in lab,red,red)){.bg-background\/80{background-color:color-mix(in oklab,hsl(var(--background))80%,transparent)}}.bg-background\/95{background-color:hsl(var(--background))}@supports (color:color-mix(in lab,red,red)){.bg-background\/95{background-color:color-mix(in oklab,hsl(var(--background))95%,transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-border,.bg-border\/60{background-color:hsl(var(--border))}@supports (color:color-mix(in lab,red,red)){.bg-border\/60{background-color:color-mix(in oklab,hsl(var(--border))60%,transparent)}}.bg-card{background-color:hsl(var(--card))}.bg-data-blue{background-color:hsl(var(--data-blue))}.bg-data-blue-bg{background-color:hsl(var(--data-blue-bg))}.bg-data-blue\/10{background-color:hsl(var(--data-blue))}@supports (color:color-mix(in lab,red,red)){.bg-data-blue\/10{background-color:color-mix(in oklab,hsl(var(--data-blue))10%,transparent)}}.bg-destructive{background-color:hsl(var(--destructive))}.bg-destructive-bg{background-color:hsl(var(--destructive-bg))}.bg-destructive\/10{background-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/10{background-color:color-mix(in oklab,hsl(var(--destructive))10%,transparent)}}.bg-header-bg{background-color:hsl(var(--header-bg))}.bg-muted{background-color:hsl(var(--muted))}.bg-muted-foreground\/30{background-color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.bg-muted-foreground\/30{background-color:color-mix(in oklab,hsl(var(--muted-foreground))30%,transparent)}}.bg-muted\/10{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/10{background-color:color-mix(in oklab,hsl(var(--muted))10%,transparent)}}.bg-muted\/30{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/30{background-color:color-mix(in oklab,hsl(var(--muted))30%,transparent)}}.bg-muted\/40{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/40{background-color:color-mix(in oklab,hsl(var(--muted))40%,transparent)}}.bg-muted\/50{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/50{background-color:color-mix(in oklab,hsl(var(--muted))50%,transparent)}}.bg-muted\/60{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/60{background-color:color-mix(in oklab,hsl(var(--muted))60%,transparent)}}.bg-muted\/80{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.bg-muted\/80{background-color:color-mix(in oklab,hsl(var(--muted))80%,transparent)}}.bg-popover{background-color:hsl(var(--popover))}.bg-primary{background-color:hsl(var(--primary))}.bg-primary-foreground\/10{background-color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.bg-primary-foreground\/10{background-color:color-mix(in oklab,hsl(var(--primary-foreground))10%,transparent)}}.bg-primary-foreground\/20{background-color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.bg-primary-foreground\/20{background-color:color-mix(in oklab,hsl(var(--primary-foreground))20%,transparent)}}.bg-primary\/5{background-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.bg-primary\/5{background-color:color-mix(in oklab,hsl(var(--primary))5%,transparent)}}.bg-primary\/10{background-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.bg-primary\/10{background-color:color-mix(in oklab,hsl(var(--primary))10%,transparent)}}.bg-primary\/70{background-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.bg-primary\/70{background-color:color-mix(in oklab,hsl(var(--primary))70%,transparent)}}.bg-secondary{background-color:hsl(var(--secondary))}.bg-sidebar{background-color:hsl(var(--sidebar))}.bg-sidebar-accent,.bg-sidebar-accent\/40{background-color:hsl(var(--sidebar-accent))}@supports (color:color-mix(in lab,red,red)){.bg-sidebar-accent\/40{background-color:color-mix(in oklab,hsl(var(--sidebar-accent))40%,transparent)}}.bg-sidebar-accent\/60{background-color:hsl(var(--sidebar-accent))}@supports (color:color-mix(in lab,red,red)){.bg-sidebar-accent\/60{background-color:color-mix(in oklab,hsl(var(--sidebar-accent))60%,transparent)}}.bg-sidebar-border,.bg-sidebar-border\/70{background-color:hsl(var(--sidebar-border))}@supports (color:color-mix(in lab,red,red)){.bg-sidebar-border\/70{background-color:color-mix(in oklab,hsl(var(--sidebar-border))70%,transparent)}}.bg-success{background-color:hsl(var(--success))}.bg-success-bg{background-color:hsl(var(--success-bg))}.bg-success\/10{background-color:hsl(var(--success))}@supports (color:color-mix(in lab,red,red)){.bg-success\/10{background-color:color-mix(in oklab,hsl(var(--success))10%,transparent)}}.bg-surface-chat{background-color:hsl(var(--surface-chat))}.bg-surface-editor{background-color:hsl(var(--surface-editor))}.bg-surface-preview{background-color:hsl(var(--surface-preview))}.bg-transparent{background-color:#0000}.bg-warning{background-color:hsl(var(--warning))}.bg-warning-bg{background-color:hsl(var(--warning-bg))}.bg-warning\/10{background-color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.bg-warning\/10{background-color:color-mix(in oklab,hsl(var(--warning))10%,transparent)}}.bg-warning\/15{background-color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.bg-warning\/15{background-color:color-mix(in oklab,hsl(var(--warning))15%,transparent)}}.bg-warning\/20{background-color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.bg-warning\/20{background-color:color-mix(in oklab,hsl(var(--warning))20%,transparent)}}.bg-warning\/60{background-color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.bg-warning\/60{background-color:color-mix(in oklab,hsl(var(--warning))60%,transparent)}}.bg-white{background-color:var(--color-white)}.fill-current{fill:currentColor}.fill-primary{fill:hsl(var(--primary))}.object-cover{object-fit:cover}.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-2\.5{padding:calc(var(--spacing)*2.5)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.p-\[1px\]{padding:1px}.px-0{padding-inline:calc(var(--spacing)*0)}.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-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0{padding-block:calc(var(--spacing)*0)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-6{padding-block:calc(var(--spacing)*6)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-0\.5{padding-top:calc(var(--spacing)*.5)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-7{padding-right:calc(var(--spacing)*7)}.pr-8{padding-right:calc(var(--spacing)*8)}.pb-0{padding-bottom:calc(var(--spacing)*0)}.pb-0\.5{padding-bottom:calc(var(--spacing)*.5)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pl-1{padding-left:calc(var(--spacing)*1)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace}.font-sans{font-family:Inter Variable,Inter,system-ui,-apple-system,Segoe UI,sans-serif}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.8rem\]{font-size:.8rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.06em\]{--tw-tracking:.06em;letter-spacing:.06em}.tracking-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-balance{text-wrap:balance}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent-foreground{color:hsl(var(--accent-foreground))}.text-accent2{color:hsl(var(--accent2))}.text-card-foreground{color:hsl(var(--card-foreground))}.text-current{color:currentColor}.text-data-blue{color:hsl(var(--data-blue))}.text-data-blue-bg-foreground{color:hsl(var(--data-blue-bg-foreground))}.text-destructive{color:hsl(var(--destructive))}.text-destructive-bg-foreground{color:hsl(var(--destructive-bg-foreground))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-destructive\/80{color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.text-destructive\/80{color:color-mix(in oklab,hsl(var(--destructive))80%,transparent)}}.text-foreground,.text-foreground\/50{color:hsl(var(--foreground))}@supports (color:color-mix(in lab,red,red)){.text-foreground\/50{color:color-mix(in oklab,hsl(var(--foreground))50%,transparent)}}.text-foreground\/80{color:hsl(var(--foreground))}@supports (color:color-mix(in lab,red,red)){.text-foreground\/80{color:color-mix(in oklab,hsl(var(--foreground))80%,transparent)}}.text-muted-foreground,.text-muted-foreground\/60{color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/60{color:color-mix(in oklab,hsl(var(--muted-foreground))60%,transparent)}}.text-muted-foreground\/70{color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/70{color:color-mix(in oklab,hsl(var(--muted-foreground))70%,transparent)}}.text-muted-foreground\/80{color:hsl(var(--muted-foreground))}@supports (color:color-mix(in lab,red,red)){.text-muted-foreground\/80{color:color-mix(in oklab,hsl(var(--muted-foreground))80%,transparent)}}.text-popover-foreground{color:hsl(var(--popover-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-foreground,.text-primary-foreground\/50{color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.text-primary-foreground\/50{color:color-mix(in oklab,hsl(var(--primary-foreground))50%,transparent)}}.text-primary-foreground\/60{color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.text-primary-foreground\/60{color:color-mix(in oklab,hsl(var(--primary-foreground))60%,transparent)}}.text-primary\/60{color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.text-primary\/60{color:color-mix(in oklab,hsl(var(--primary))60%,transparent)}}.text-secondary-foreground{color:hsl(var(--secondary-foreground))}.text-sidebar-accent-foreground,.text-sidebar-accent-foreground\/70{color:hsl(var(--sidebar-accent-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-accent-foreground\/70{color:color-mix(in oklab,hsl(var(--sidebar-accent-foreground))70%,transparent)}}.text-sidebar-foreground,.text-sidebar-foreground\/40{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/40{color:color-mix(in oklab,hsl(var(--sidebar-foreground))40%,transparent)}}.text-sidebar-foreground\/45{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/45{color:color-mix(in oklab,hsl(var(--sidebar-foreground))45%,transparent)}}.text-sidebar-foreground\/50{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/50{color:color-mix(in oklab,hsl(var(--sidebar-foreground))50%,transparent)}}.text-sidebar-foreground\/55{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/55{color:color-mix(in oklab,hsl(var(--sidebar-foreground))55%,transparent)}}.text-sidebar-foreground\/60{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/60{color:color-mix(in oklab,hsl(var(--sidebar-foreground))60%,transparent)}}.text-sidebar-foreground\/65{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/65{color:color-mix(in oklab,hsl(var(--sidebar-foreground))65%,transparent)}}.text-sidebar-foreground\/70{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/70{color:color-mix(in oklab,hsl(var(--sidebar-foreground))70%,transparent)}}.text-sidebar-foreground\/80{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/80{color:color-mix(in oklab,hsl(var(--sidebar-foreground))80%,transparent)}}.text-sidebar-foreground\/85{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.text-sidebar-foreground\/85{color:color-mix(in oklab,hsl(var(--sidebar-foreground))85%,transparent)}}.text-success{color:hsl(var(--success))}.text-success-bg-foreground{color:hsl(var(--success-bg-foreground))}.text-warning{color:hsl(var(--warning))}.text-warning-bg-foreground{color:hsl(var(--warning-bg-foreground))}.text-warning\/80{color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.text-warning\/80{color:color-mix(in oklab,hsl(var(--warning))80%,transparent)}}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.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-\[0_0_0_1px_hsl\(var\(--sidebar-border\)\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,hsl(var(--sidebar-border)));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[inset_0_-2px_0_hsl\(var\(--ring\)\)\]{--tw-shadow:inset 0 -2px 0 var(--tw-shadow-color,hsl(var(--ring)));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_2px_0_hsl\(var\(--ring\)\)\]{--tw-shadow:inset 0 2px 0 var(--tw-shadow-color,hsl(var(--ring)));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-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-0{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-\[hsl\(var\(--sidebar\)\)\]{--tw-ring-color:hsl(var(--sidebar))}.ring-primary\/40{--tw-ring-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.ring-primary\/40{--tw-ring-color:color-mix(in oklab,hsl(var(--primary))40%,transparent)}}.ring-sidebar-ring{--tw-ring-color:hsl(var(--sidebar-ring))}.ring-offset-background{--tw-ring-offset-color:hsl(var(--background))}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.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-\[2px\]{--tw-backdrop-blur:blur(2px);-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,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,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-\[left\,right\,width\]{transition-property:left,right,width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[margin\,opa\]{transition-property:margin,opa;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\,height\,padding\]{transition-property:width,height,padding;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-\[cubic-bezier\(0\.16\,1\,0\.3\,1\)\]{--tw-ease:cubic-bezier(.16,1,.3,1);transition-timing-function:cubic-bezier(.16,1,.3,1)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.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}.duration-100{animation-duration:.1s}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.ease-\[cubic-bezier\(0\.16\,1\,0\.3\,1\)\]{animation-timing-function:cubic-bezier(.16,1,.3,1)}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-linear{animation-timing-function:linear}.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}.group-focus-within\/menu-item\:opacity-0:is(:where(.group\/menu-item):focus-within *){opacity:0}.group-focus-within\/menu-item\:opacity-100:is(:where(.group\/menu-item):focus-within *){opacity:1}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\/menu-item\:opacity-0:is(:where(.group\/menu-item):hover *){opacity:0}.group-hover\/menu-item\:opacity-100:is(:where(.group\/menu-item):hover *),.group-hover\/msg\:opacity-100:is(:where(.group\/msg):hover *),.group-hover\/row\:opacity-100:is(:where(.group\/row):hover *){opacity:1}}.group-focus-visible\/row\:opacity-100:is(:where(.group\/row):focus-visible *){opacity:1}.group-has-\[\[data-sidebar\=menu-action\]\]\/menu-item\:pr-8:is(:where(.group\/menu-item):has([data-sidebar=menu-action]) *){padding-right:calc(var(--spacing)*8)}.group-data-\[collapsible\=icon\]\:-mt-8:is(:where(.group)[data-collapsible=icon] *){margin-top:calc(var(--spacing)*-8)}.group-data-\[collapsible\=icon\]\:hidden:is(:where(.group)[data-collapsible=icon] *){display:none}.group-data-\[collapsible\=icon\]\:\!size-8:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--spacing)*8)!important;height:calc(var(--spacing)*8)!important}.group-data-\[collapsible\=icon\]\:w-\[--sidebar-width-icon\]:is(:where(.group)[data-collapsible=icon] *){width:--sidebar-width-icon}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)_\+_theme\(spacing\.4\)\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + 1rem)}.group-data-\[collapsible\=icon\]\:w-\[calc\(var\(--sidebar-width-icon\)_\+_theme\(spacing\.4\)_\+2px\)\]:is(:where(.group)[data-collapsible=icon] *){width:calc(var(--sidebar-width-icon) + 1rem + 2px)}.group-data-\[collapsible\=icon\]\:overflow-hidden:is(:where(.group)[data-collapsible=icon] *){overflow:hidden}.group-data-\[collapsible\=icon\]\:\!p-0:is(:where(.group)[data-collapsible=icon] *){padding:calc(var(--spacing)*0)!important}.group-data-\[collapsible\=icon\]\:\!p-2:is(:where(.group)[data-collapsible=icon] *){padding:calc(var(--spacing)*2)!important}.group-data-\[collapsible\=icon\]\:opacity-0:is(:where(.group)[data-collapsible=icon] *){opacity:0}.group-data-\[collapsible\=offcanvas\]\:right-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){right:calc(var(--sidebar-width)*-1)}.group-data-\[collapsible\=offcanvas\]\:left-\[calc\(var\(--sidebar-width\)\*-1\)\]:is(:where(.group)[data-collapsible=offcanvas] *){left:calc(var(--sidebar-width)*-1)}.group-data-\[collapsible\=offcanvas\]\:w-0:is(:where(.group)[data-collapsible=offcanvas] *){width:calc(var(--spacing)*0)}.group-data-\[collapsible\=offcanvas\]\:translate-x-0:is(:where(.group)[data-collapsible=offcanvas] *){--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.group-data-\[side\=left\]\:-right-4:is(:where(.group)[data-side=left] *){right:calc(var(--spacing)*-4)}.group-data-\[side\=left\]\:border-r:is(:where(.group)[data-side=left] *){border-right-style:var(--tw-border-style);border-right-width:1px}.group-data-\[side\=right\]\:left-0:is(:where(.group)[data-side=right] *){left:calc(var(--spacing)*0)}.group-data-\[side\=right\]\:rotate-180:is(:where(.group)[data-side=right] *){rotate:180deg}.group-data-\[side\=right\]\:border-l:is(:where(.group)[data-side=right] *){border-left-style:var(--tw-border-style);border-left-width:1px}.group-data-\[variant\=floating\]\:rounded-lg:is(:where(.group)[data-variant=floating] *){border-radius:var(--radius)}.group-data-\[variant\=floating\]\:border:is(:where(.group)[data-variant=floating] *){border-style:var(--tw-border-style);border-width:1px}.group-data-\[variant\=floating\]\:border-sidebar-border:is(:where(.group)[data-variant=floating] *){border-color:hsl(var(--sidebar-border))}.group-data-\[variant\=floating\]\:shadow:is(:where(.group)[data-variant=floating] *){--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)}.group-\[\.destructive\]\:border-muted\/40:is(:where(.group).destructive *){border-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:border-muted\/40:is(:where(.group).destructive *){border-color:color-mix(in oklab,hsl(var(--muted))40%,transparent)}}.group-\[\.destructive\]\:text-destructive-foreground\/70:is(:where(.group).destructive *){color:hsl(var(--destructive-foreground))}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:text-destructive-foreground\/70:is(:where(.group).destructive *){color:color-mix(in oklab,hsl(var(--destructive-foreground))70%,transparent)}}@media (hover:hover){.peer-hover\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button):hover~*){color:hsl(var(--sidebar-accent-foreground))}}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.peer-data-\[active\=true\]\/menu-button\:text-sidebar-accent-foreground:is(:where(.peer\/menu-button)[data-active=true]~*){color:hsl(var(--sidebar-accent-foreground))}.peer-data-\[size\=default\]\/menu-button\:top-1\.5:is(:where(.peer\/menu-button)[data-size=default]~*){top:calc(var(--spacing)*1.5)}.peer-data-\[size\=lg\]\/menu-button\:top-2\.5:is(:where(.peer\/menu-button)[data-size=lg]~*){top:calc(var(--spacing)*2.5)}.peer-data-\[size\=sm\]\/menu-button\:top-1:is(:where(.peer\/menu-button)[data-size=sm]~*){top:calc(var(--spacing)*1)}.peer-data-\[variant\=inset\]\:min-h-\[calc\(100svh-theme\(spacing\.4\)\)\]:is(:where(.peer)[data-variant=inset]~*){min-height:calc(100svh - 1rem)}.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:hsl(var(--foreground))}.placeholder\:overflow-hidden::placeholder{overflow:hidden}.placeholder\:text-ellipsis::placeholder{text-overflow:ellipsis}.placeholder\:whitespace-nowrap::placeholder{white-space:nowrap}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.placeholder\:text-sidebar-foreground\/60::placeholder{color:hsl(var(--sidebar-foreground))}@supports (color:color-mix(in lab,red,red)){.placeholder\:text-sidebar-foreground\/60::placeholder{color:color-mix(in oklab,hsl(var(--sidebar-foreground))60%,transparent)}}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:-inset-2:after{content:var(--tw-content);inset:calc(var(--spacing)*-2)}.after\:inset-y-0:after{content:var(--tw-content);inset-block:calc(var(--spacing)*0)}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-1:after{content:var(--tw-content);width:calc(var(--spacing)*1)}.after\:w-\[2px\]:after{content:var(--tw-content);width:2px}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.group-data-\[collapsible\=offcanvas\]\:after\:left-full:is(:where(.group)[data-collapsible=offcanvas] *):after{content:var(--tw-content);left:100%}.focus-within\:opacity-100:focus-within{opacity:1}@media (hover:hover){.hover\:bg-accent:hover,.hover\:bg-accent\/50:hover{background-color:hsl(var(--accent))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/50:hover{background-color:color-mix(in oklab,hsl(var(--accent))50%,transparent)}}.hover\:bg-destructive\/15:hover{background-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/15:hover{background-color:color-mix(in oklab,hsl(var(--destructive))15%,transparent)}}.hover\:bg-destructive\/20:hover{background-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/20:hover{background-color:color-mix(in oklab,hsl(var(--destructive))20%,transparent)}}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,hsl(var(--destructive))90%,transparent)}}.hover\:bg-muted:hover,.hover\:bg-muted\/30:hover{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/30:hover{background-color:color-mix(in oklab,hsl(var(--muted))30%,transparent)}}.hover\:bg-muted\/40:hover{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/40:hover{background-color:color-mix(in oklab,hsl(var(--muted))40%,transparent)}}.hover\:bg-muted\/50:hover{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,hsl(var(--muted))50%,transparent)}}.hover\:bg-muted\/60:hover{background-color:hsl(var(--muted))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/60:hover{background-color:color-mix(in oklab,hsl(var(--muted))60%,transparent)}}.hover\:bg-primary-foreground\/20:hover{background-color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary-foreground\/20:hover{background-color:color-mix(in oklab,hsl(var(--primary-foreground))20%,transparent)}}.hover\:bg-primary\/10:hover{background-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/10:hover{background-color:color-mix(in oklab,hsl(var(--primary))10%,transparent)}}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,hsl(var(--primary))90%,transparent)}}.hover\:bg-secondary:hover,.hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,hsl(var(--secondary))80%,transparent)}}.hover\:bg-sidebar-accent:hover,.hover\:bg-sidebar-accent\/60:hover{background-color:hsl(var(--sidebar-accent))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-sidebar-accent\/60:hover{background-color:color-mix(in oklab,hsl(var(--sidebar-accent))60%,transparent)}}.hover\:bg-warning\/20:hover{background-color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.hover\:bg-warning\/20:hover{background-color:color-mix(in oklab,hsl(var(--warning))20%,transparent)}}.hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:text-destructive:hover,.hover\:text-destructive\/80:hover{color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.hover\:text-destructive\/80:hover{color:color-mix(in oklab,hsl(var(--destructive))80%,transparent)}}.hover\:text-foreground:hover,.hover\:text-foreground\/80:hover{color:hsl(var(--foreground))}@supports (color:color-mix(in lab,red,red)){.hover\:text-foreground\/80:hover{color:color-mix(in oklab,hsl(var(--foreground))80%,transparent)}}.hover\:text-primary-foreground\/80:hover{color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){.hover\:text-primary-foreground\/80:hover{color:color-mix(in oklab,hsl(var(--primary-foreground))80%,transparent)}}.hover\:text-primary\/80:hover{color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.hover\:text-primary\/80:hover{color:color-mix(in oklab,hsl(var(--primary))80%,transparent)}}.hover\:text-sidebar-accent-foreground:hover{color:hsl(var(--sidebar-accent-foreground))}.hover\:text-sidebar-foreground:hover{color:hsl(var(--sidebar-foreground))}.hover\:text-warning\/80:hover{color:hsl(var(--warning))}@supports (color:color-mix(in lab,red,red)){.hover\:text-warning\/80:hover{color:color-mix(in oklab,hsl(var(--warning))80%,transparent)}}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-\[0_0_0_1px_hsl\(var\(--sidebar-accent\)\)\]:hover{--tw-shadow:0 0 0 1px var(--tw-shadow-color,hsl(var(--sidebar-accent)));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.group-data-\[collapsible\=offcanvas\]\:hover\:bg-sidebar:is(:where(.group)[data-collapsible=offcanvas] *):hover{background-color:hsl(var(--sidebar))}.group-\[\.destructive\]\:hover\:border-destructive\/30:is(:where(.group).destructive *):hover{border-color:hsl(var(--destructive))}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:hover\:border-destructive\/30:is(:where(.group).destructive *):hover{border-color:color-mix(in oklab,hsl(var(--destructive))30%,transparent)}}.group-\[\.destructive\]\:hover\:bg-destructive:is(:where(.group).destructive *):hover{background-color:hsl(var(--destructive))}.group-\[\.destructive\]\:hover\:text-destructive-foreground:is(:where(.group).destructive *):hover{color:hsl(var(--destructive-foreground))}.hover\:after\:bg-sidebar-border:hover:after{content:var(--tw-content);background-color:hsl(var(--sidebar-border))}}.focus\:bg-accent:focus{background-color:hsl(var(--accent))}.focus\:text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.focus\:text-destructive:focus{color:hsl(var(--destructive))}.focus\:opacity-100:focus{opacity:1}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-primary\/40:focus{--tw-ring-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.focus\:ring-primary\/40:focus{--tw-ring-color:color-mix(in oklab,hsl(var(--primary))40%,transparent)}}.focus\:ring-ring:focus{--tw-ring-color:hsl(var(--ring))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.group-\[\.destructive\]\:focus\:ring-destructive:is(:where(.group).destructive *):focus{--tw-ring-color:hsl(var(--destructive))}.group-\[\.destructive\]\:focus\:ring-destructive-foreground\/40:is(:where(.group).destructive *):focus{--tw-ring-color:hsl(var(--destructive-foreground))}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:focus\:ring-destructive-foreground\/40:is(:where(.group).destructive *):focus{--tw-ring-color:color-mix(in oklab,hsl(var(--destructive-foreground))40%,transparent)}}.focus-visible\:h-9:focus-visible{height:calc(var(--spacing)*9)}.focus-visible\:border-primary\/50:focus-visible{border-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.focus-visible\:border-primary\/50:focus-visible{border-color:color-mix(in oklab,hsl(var(--primary))50%,transparent)}}.focus-visible\:border-sidebar-ring:focus-visible{border-color:hsl(var(--sidebar-ring))}.focus-visible\:bg-sidebar-accent\/60:focus-visible{background-color:hsl(var(--sidebar-accent))}@supports (color:color-mix(in lab,red,red)){.focus-visible\:bg-sidebar-accent\/60:focus-visible{background-color:color-mix(in oklab,hsl(var(--sidebar-accent))60%,transparent)}}.focus-visible\:opacity-100:focus-visible{opacity:1}.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-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-primary\/30:focus-visible{--tw-ring-color:hsl(var(--primary))}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-primary\/30:focus-visible{--tw-ring-color:color-mix(in oklab,hsl(var(--primary))30%,transparent)}}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.focus-visible\:ring-sidebar-ring:focus-visible{--tw-ring-color:hsl(var(--sidebar-ring))}.focus-visible\:ring-offset-0:focus-visible{--tw-ring-offset-width:0px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color:hsl(var(--background))}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:bg-sidebar-accent:active{background-color:hsl(var(--sidebar-accent))}.active\:text-sidebar-accent-foreground:active{color:hsl(var(--sidebar-accent-foreground))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\[data-variant\=inset\]\]\:bg-sidebar:has([data-variant=inset]){background-color:hsl(var(--sidebar))}.aria-disabled\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\:opacity-50[aria-disabled=true]{opacity:.5}.data-\[active\=true\]\:bg-sidebar-accent[data-active=true]{background-color:hsl(var(--sidebar-accent))}.data-\[active\=true\]\:font-medium[data-active=true]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.data-\[active\=true\]\:text-sidebar-accent-foreground[data-active=true]{color:hsl(var(--sidebar-accent-foreground))}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[panel-group-direction\=vertical\]\:h-px[data-panel-group-direction=vertical]{height:1px}.data-\[panel-group-direction\=vertical\]\:w-full[data-panel-group-direction=vertical]{width:100%}.data-\[panel-group-direction\=vertical\]\:flex-col[data-panel-group-direction=vertical]{flex-direction:column}.data-\[panel-group-direction\=vertical\]\:after\:left-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);left:calc(var(--spacing)*0)}.data-\[panel-group-direction\=vertical\]\:after\:h-1[data-panel-group-direction=vertical]:after{content:var(--tw-content);height:calc(var(--spacing)*1)}.data-\[panel-group-direction\=vertical\]\:after\:w-full[data-panel-group-direction=vertical]:after{content:var(--tw-content);width:100%}.data-\[panel-group-direction\=vertical\]\:after\:translate-x-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[panel-group-direction\=vertical\]\:after\:-translate-y-1\/2[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:-.5rem}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:.5rem}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:-.5rem}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:.5rem}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:hsl(var(--background))}.data-\[state\=active\]\:text-foreground[data-state=active]{color:hsl(var(--foreground))}.data-\[state\=checked\]\:translate-x-\[calc\(100\%-2px\)\][data-state=checked]{--tw-translate-x: calc(100% - 2px) ;translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:hsl(var(--primary))}.data-\[state\=closed\]\:duration-300[data-state=closed]{--tw-duration:.3s;transition-duration:.3s}.data-\[state\=closed\]\:animate-out[data-state=closed]{--tw-exit-opacity:initial;--tw-exit-scale:initial;--tw-exit-rotate:initial;--tw-exit-translate-x:initial;--tw-exit-translate-y:initial;animation-name:exit;animation-duration:.15s}.data-\[state\=closed\]\:duration-300[data-state=closed]{animation-duration:.3s}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y:100%}.data-\[state\=closed\]\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x:-100%}.data-\[state\=closed\]\:slide-out-to-right[data-state=closed]{--tw-exit-translate-x:100%}.data-\[state\=closed\]\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y:-100%}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:hsl(var(--accent))}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:hsl(var(--secondary))}.data-\[state\=open\]\:text-accent-foreground[data-state=open]{color:hsl(var(--accent-foreground))}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:hsl(var(--muted-foreground))}.data-\[state\=open\]\:opacity-100[data-state=open]{opacity:1}.data-\[state\=open\]\:duration-500[data-state=open]{--tw-duration:.5s;transition-duration:.5s}.data-\[state\=open\]\:animate-in[data-state=open]{--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}.data-\[state\=open\]\:duration-500[data-state=open]{animation-duration:.5s}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y:100%}.data-\[state\=open\]\:slide-in-from-left[data-state=open]{--tw-enter-translate-x:-100%}.data-\[state\=open\]\:slide-in-from-right[data-state=open]{--tw-enter-translate-x:100%}.data-\[state\=open\]\:slide-in-from-top[data-state=open]{--tw-enter-translate-y:-100%}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}@media (hover:hover){.data-\[state\=open\]\:hover\:bg-sidebar-accent[data-state=open]:hover{background-color:hsl(var(--sidebar-accent))}.data-\[state\=open\]\:hover\:text-sidebar-accent-foreground[data-state=open]:hover{color:hsl(var(--sidebar-accent-foreground))}}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[state\=unchecked\]\:bg-switch-off[data-state=unchecked]{background-color:hsl(var(--switch-off))}@media (min-width:40rem){.sm\:top-auto{top:auto}.sm\:right-0{right:calc(var(--spacing)*0)}.sm\:bottom-0{bottom:calc(var(--spacing)*0)}.sm\:flex{display:flex}.sm\:inline{display:inline}.sm\:max-w-5xl{max-width:var(--container-5xl)}.sm\:max-w-\[425px\]{max-width:425px}.sm\:max-w-\[525px\]{max-width:525px}.sm\:max-w-\[560px\]{max-width:560px}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:flex-col{flex-direction:column}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}:where(.sm\:space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:text-left{text-align:left}}@media (min-width:48rem){.md\:block{display:block}.md\:flex{display:flex}.md\:max-w-\[420px\]{max-width:420px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:opacity-0{opacity:0}.md\:peer-data-\[variant\=inset\]\:m-2:is(:where(.peer)[data-variant=inset]~*){margin:calc(var(--spacing)*2)}.md\:peer-data-\[variant\=inset\]\:ml-0:is(:where(.peer)[data-variant=inset]~*){margin-left:calc(var(--spacing)*0)}.md\:peer-data-\[variant\=inset\]\:rounded-xl:is(:where(.peer)[data-variant=inset]~*){border-radius:var(--radius-xl)}.md\:peer-data-\[variant\=inset\]\:shadow:is(:where(.peer)[data-variant=inset]~*){--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)}.md\:peer-data-\[state\=collapsed\]\:peer-data-\[variant\=inset\]\:ml-2:is(:where(.peer)[data-state=collapsed]~*):is(:where(.peer)[data-variant=inset]~*){margin-left:calc(var(--spacing)*2)}}.after\:md\:hidden:after{content:var(--tw-content)}@media (min-width:48rem){.after\:md\:hidden:after{display:none}}@media (min-width:64rem){.lg\:flex{display:flex}.lg\:hidden{display:none}}.dark\:block:where(.dark,.dark *){display:block}.dark\:hidden:where(.dark,.dark *){display:none}.dark\:scale-0:where(.dark,.dark *){--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.dark\:scale-100:where(.dark,.dark *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.dark\:-rotate-90:where(.dark,.dark *){rotate:-90deg}.dark\:rotate-0:where(.dark,.dark *){rotate:none}.\[\&_\[data-radix-scroll-area-viewport\]\>div\]\:\!block [data-radix-scroll-area-viewport]>div{display:block!important}.\[\&_h1\]\:my-2 h1{margin-block:calc(var(--spacing)*2)}.\[\&_h1\]\:text-base h1{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.\[\&_h2\]\:my-1\.5 h2{margin-block:calc(var(--spacing)*1.5)}.\[\&_h2\]\:text-sm h2{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.\[\&_h3\]\:my-1 h3{margin-block:calc(var(--spacing)*1)}.\[\&_h3\]\:text-sm h3{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.\[\&_li\]\:my-0\.5 li{margin-block:calc(var(--spacing)*.5)}.\[\&_ol\]\:my-1 ol,.\[\&_p\]\:my-1 p{margin-block:calc(var(--spacing)*1)}.\[\&_p\]\:leading-relaxed p{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_pre\]\:overflow-x-auto pre{overflow-x:auto}.\[\&_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\]\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_ul\]\:my-1 ul{margin-block:calc(var(--spacing)*1)}.\[\&\>button\]\:hidden>button{display:none}.\[\&\>div\>div\]\:\!h-full>div>div{height:100%!important}.\[\&\>span\]\:min-w-0>span{min-width:calc(var(--spacing)*0)}.\[\&\>span\]\:break-words>span{overflow-wrap:break-word}.\[\&\>span\]\:whitespace-normal>span{white-space:normal}.\[\&\>span\:last-child\]\:truncate>span:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:top-4>svg{top:calc(var(--spacing)*4)}.\[\&\>svg\]\:left-4>svg{left:calc(var(--spacing)*4)}.\[\&\>svg\]\:size-3\.5>svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}.\[\&\>svg\]\:text-data-blue-bg-foreground>svg{color:hsl(var(--data-blue-bg-foreground))}.\[\&\>svg\]\:text-destructive-bg-foreground>svg{color:hsl(var(--destructive-bg-foreground))}.\[\&\>svg\]\:text-foreground>svg{color:hsl(var(--foreground))}.\[\&\>svg\]\:text-sidebar-accent-foreground>svg{color:hsl(var(--sidebar-accent-foreground))}.\[\&\>svg\]\:text-success-bg-foreground>svg{color:hsl(var(--success-bg-foreground))}.\[\&\>svg\]\:text-warning-bg-foreground>svg{color:hsl(var(--warning-bg-foreground))}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y:-3px;translate:var(--tw-translate-x)var(--tw-translate-y)}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:calc(var(--spacing)*7)}.\[\&\[data-panel-group-direction\=vertical\]\>div\]\:rotate-90[data-panel-group-direction=vertical]>div{rotate:90deg}[data-side=left] .\[\[data-side\=left\]_\&\]\:cursor-w-resize{cursor:w-resize}[data-side=left][data-collapsible=offcanvas] .\[\[data-side\=left\]\[data-collapsible\=offcanvas\]_\&\]\:-right-2{right:calc(var(--spacing)*-2)}[data-side=left][data-state=collapsed] .\[\[data-side\=left\]\[data-state\=collapsed\]_\&\]\:cursor-e-resize,[data-side=right] .\[\[data-side\=right\]_\&\]\:cursor-e-resize{cursor:e-resize}[data-side=right][data-collapsible=offcanvas] .\[\[data-side\=right\]\[data-collapsible\=offcanvas\]_\&\]\:-left-2{left:calc(var(--spacing)*-2)}[data-side=right][data-state=collapsed] .\[\[data-side\=right\]\[data-state\=collapsed\]_\&\]\:cursor-w-resize{cursor:w-resize}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-primary-foreground\/20{background-color:hsl(var(--primary-foreground))}@supports (color:color-mix(in lab,red,red)){[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:bg-primary-foreground\/20{background-color:color-mix(in oklab,hsl(var(--primary-foreground))20%,transparent)}}[data-slot=tooltip-content] .\[\[data-slot\=tooltip-content\]_\&\]\:text-primary-foreground{color:hsl(var(--primary-foreground))}}*{scrollbar-width:thin;scrollbar-color:hsl(var(--border))transparent}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:hsl(var(--border));border-radius:3px}::-webkit-scrollbar-thumb:hover{background:hsl(var(--muted-foreground)/.4)}.jto-outline-flash{background:hsl(var(--ring)/.16);border-radius:2px}@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-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}@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-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}@keyframes progress-indeterminate{0%{transform:translate(-100%)}to{transform:translate(350%)}}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/docx-preview-DQa8jhzH.js","assets/react-vendor-CTFDOf2G.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{r as x,j as e,c as A}from"./react-vendor-CTFDOf2G.js";import{S as T,c as S,h as ce,F as b,j as te,k as Ee,P as Re,W as ke,_ as Ce,p as Le,A as H}from"./index-CRuLxurM.js";import{S as O,B as Fe,P as Oe,b as $e,D as Me,c as De,d as Te,e as Ae}from"./HomePage-DgVVosCp.js";import{B as le}from"./editor-refs-store-DNQzN0_z.js";import{e as Ie,Q as J,w as de}from"./ui-vendor-DyQLnWB8.js";import{u as E,a as ue,d as se,b as Be}from"./MonacoPluginProvider-DiUyU9px.js";import{ag as me,ah as Pe}from"./radix-ui-Bq-7y_Sq.js";import"./query-vendor-Df8-oete.js";import"./monaco-editor-BcgxPCqT.js";import"./state-vendor-ByFYl9bq.js";var ze=["fonts.gstatic.com","fonts.googleapis.com","cdn.jsdelivr.net"];function _e(t){let r;try{r=new URL(t)}catch{return!1}return r.protocol!=="https:"?!1:ze.includes(r.hostname.toLowerCase())}function fe(t){const[r]=x.useState(()=>Date.now()),s=t??r,[o,n]=x.useState(()=>Date.now());return x.useEffect(()=>{const a=setInterval(()=>n(Date.now()),100);return()=>clearInterval(a)},[]),Math.max(0,(o-s)/1e3)}function Ue(t){var r,s;if(!t)return null;try{const o=JSON.parse(t);if(!o||typeof o!="object")return null;const n=new Map,a=[o];for(;a.length>0;){const c=a.pop();if(!c||typeof c!="object")continue;const{name:u,children:f}=c;typeof u=="string"&&n.set(u,(n.get(u)??0)+1),Array.isArray(f)&&a.push(...f)}const l=[["slide","slide","slides"],["section","section","sections"],["visual","visual","visuals"],["chart","chart","charts"],["image","image","images"],["table","table","tables"],["shape","shape","shapes"],["paragraph","paragraph","paragraphs"]].map(([c,u,f])=>{const m=n.get(c)??0;return{label:m===1?u:f,count:m}}).filter(c=>c.count>0).slice(0,5),d=(s=(r=o.props)==null?void 0:r.metadata)==null?void 0:s.title;return{title:typeof d=="string"?d:void 0,counts:l,visualCount:(n.get("visual")??0)+(n.get("chart")??0),imageCount:n.get("image")??0}}catch{return null}}function We(t){const r=[];return t&&t.visualCount>0&&r.push(`${t.visualCount} visual${t.visualCount===1?"":"s"} in this document ${t.visualCount===1?"is":"are"} rasterized on first build — later builds reuse the cached renders.`),t&&t.imageCount>3&&r.push("Large embedded images dominate build time — downscaling them speeds up iteration."),r.push("Re-running an unchanged document is served from the cache almost instantly.","Generation warnings, if any, will appear above the preview when the build completes."),r}const Ge=()=>e.jsx("svg",{className:"h-3.5 w-3.5 text-success",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M3 8.5L6.5 12L13 4.5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})});function He({className:t,currentStage:r="parsing",message:s,documentText:o,startedAt:n,onCancel:a}){const i=["parsing","building","rendering","finalizing"],l={parsing:"Validating JSON",building:"Building structure",rendering:"Rendering content",finalizing:"Finalizing document"},d=i.indexOf(r),c=fe(n),u=x.useMemo(()=>Ue(o),[o]),f=x.useMemo(()=>We(u),[u]),m=c>3,g=Math.floor(Math.max(0,c-3)/5)%f.length;return e.jsxs("div",{className:S("p-6 max-w-lg mx-auto space-y-5",t),children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[e.jsx(T,{size:"md"}),e.jsxs("div",{className:"space-y-0.5 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:u!=null&&u.title?`Generating “${u.title}”`:"Generating document"}),e.jsx("p",{className:"text-xs text-muted-foreground truncate",role:"status","aria-live":"polite",children:s||`${l[r]}...`})]})]}),e.jsxs("span",{className:"shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums","aria-hidden":"true",children:[c.toFixed(1),"s"]})]}),u&&u.counts.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1.5","aria-label":"Document contents",children:u.counts.map(({label:w,count:j})=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs text-muted-foreground",children:[e.jsx("span",{className:"font-medium text-foreground tabular-nums",children:j}),w]},w))}),e.jsx("div",{className:"space-y-3",children:i.map((w,j)=>{const R=j===d,k=j<d;return e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between text-xs",children:[e.jsx("span",{className:S(R?"text-primary font-medium":k?"text-muted-foreground":"text-muted-foreground/60"),children:l[w]}),k?e.jsx(Ge,{}):R?e.jsx(T,{size:"sm",className:"h-3.5 w-3.5"}):e.jsx("span",{className:"h-3.5 w-3.5 rounded-full border border-muted-foreground/40"})]}),e.jsx("div",{className:"w-full bg-secondary rounded-full h-1.5 overflow-hidden",children:k?e.jsx("div",{className:"h-full w-full rounded-full bg-success"}):R?e.jsx("div",{className:"h-full w-2/5 rounded-full bg-primary animate-progress-indeterminate"}):null})]},w)})}),e.jsxs("div",{className:"flex items-center justify-between gap-3 min-h-8",children:[e.jsx("p",{className:S("text-xs text-muted-foreground/80 italic transition-opacity duration-500",m?"opacity-100":"opacity-0"),children:f[g]}),a&&e.jsx(le,{variant:"outline",size:"sm",onClick:a,className:"shrink-0",children:"Cancel"})]})]})}function Je({mode:t,message:r,startedAt:s,onCancel:o,className:n}){const a=fe(s);return e.jsxs("div",{className:S("flex flex-col items-center gap-2 rounded-md border bg-background/95 px-6 py-4 shadow-sm",n),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(T,{size:"md"}),e.jsx("p",{className:"text-sm font-medium",role:"status","aria-live":"polite",children:t==="generating"?"Generating":"Rendering"}),e.jsxs("span",{className:"rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums","aria-hidden":"true",children:[a.toFixed(1),"s"]})]}),r&&e.jsx("p",{className:"max-w-xs text-center text-xs text-muted-foreground truncate",children:r}),t==="generating"&&o&&e.jsx(le,{variant:"outline",size:"sm",onClick:o,children:"Cancel"})]})}function qe({renderingLibrary:t,className:r}){const s=a=>{switch(a){case"LibreOffice":return{name:"LibreOffice",description:"Converting document to PDF locally..."};case"Office":return{name:"Microsoft Office",description:"Uploading file and loading Office viewer..."};case"Docs":return{name:"Google Docs",description:"Uploading file and loading Docs viewer..."};default:return{name:"Default",description:"Processing document..."}}},{name:o,description:n}=s(t);return e.jsxs("div",{className:S("flex flex-col items-center justify-center h-full p-8 space-y-4",r),children:[e.jsx(T,{size:"lg"}),e.jsxs("div",{className:"text-center space-y-2",children:[e.jsx("p",{className:"text-sm font-medium",children:"Rendering Preview"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Using ",o," renderer"]}),e.jsx("p",{className:"text-xs text-muted-foreground/80",children:n})]}),e.jsxs("div",{className:"w-full max-w-md space-y-3",children:[e.jsx(O,{className:"h-16 w-full"}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{className:"h-4 w-full"}),e.jsx(O,{className:"h-4 w-3/4"}),e.jsx(O,{className:"h-4 w-1/2"})]}),e.jsx(O,{className:"h-12 w-full"})]})]})}const he=A.forwardRef(({isLoading:t,iframeSrc:r,iframeSrcDoc:s,isGenerating:o,generationProgress:n,generationDocumentText:a,generationStartedAt:i,onCancelGeneration:l},d)=>{const[c,u]=x.useState(!1);x.useEffect(()=>{u(!1)},[r,s]);const f=()=>{u(!0)},m=()=>{console.warn("Iframe failed to load content"),u(!1)},g=s?"allow-scripts allow-popups allow-forms":void 0,w=!!(r||s);return o&&!w?e.jsx("div",{className:"grow",children:e.jsx(He,{currentStage:n==null?void 0:n.stage,message:n==null?void 0:n.message,documentText:a,startedAt:i,onCancel:l})}):t&&!w?e.jsx("div",{className:"grow",children:e.jsx(qe,{renderingLibrary:"LibreOffice"})}):w?e.jsxs("div",{className:"h-full w-full relative bg-white",children:[!c&&e.jsx("div",{className:"absolute inset-0 bg-muted/80 flex items-center justify-center z-10",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-foreground mx-auto mb-2"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading preview..."})]})}),(o||t)&&e.jsx("div",{className:"absolute inset-0 bg-background/60 backdrop-blur-[2px] flex items-center justify-center z-20 transition-opacity duration-200",children:e.jsx(Je,{mode:o?"generating":"rendering",message:o?n==null?void 0:n.message:void 0,startedAt:o?i:void 0,onCancel:o?l:void 0})}),e.jsx("iframe",{ref:d,className:"w-full h-full border-0",style:{backgroundColor:"white",opacity:c?1:0,transition:"opacity 0.2s ease-in-out"},src:r,srcDoc:s,onLoad:f,onError:m,sandbox:g,title:"Document preview","aria-label":`Preview of rendered ${ce.toLowerCase()}`},s?"srcdoc":"src")]}):null});he.displayName="PreviewFrame";const Ve=A.memo(he);function Ke({warnings:t,className:r}){const[s,o]=A.useState(!1);return!t||t.length===0?null:e.jsxs("div",{className:r,children:[e.jsxs("button",{type:"button",onClick:()=>o(!s),className:"flex w-full items-center gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-1.5 text-left transition-colors hover:bg-warning/20",children:[e.jsx(Ie,{className:`h-3.5 w-3.5 text-warning transition-transform flex-shrink-0 ${s?"rotate-90":""}`}),e.jsx(J,{className:"h-3.5 w-3.5 text-warning flex-shrink-0"}),e.jsxs("span",{className:"text-xs font-medium text-warning",children:[t.length," warning",t.length!==1?"s":""]})]}),s&&e.jsx("div",{className:"mt-1.5 space-y-1.5",children:t.map((n,a)=>e.jsxs("div",{className:"flex items-start gap-2 rounded-sm border bg-card px-3 py-2",children:[n.severity==="info"?e.jsx(de,{className:"h-3.5 w-3.5 mt-0.5 text-data-blue flex-shrink-0"}):e.jsx(J,{className:"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("code",{className:"text-[11px] font-medium text-warning bg-warning/15 px-1 py-0.5 rounded-sm",children:n.component}),n.severity==="info"&&e.jsx("span",{className:"text-[10px] uppercase tracking-wide text-data-blue font-medium",children:"info"})]}),e.jsx("p",{className:"mt-0.5 text-xs text-muted-foreground leading-relaxed",children:n.message}),n.context&&Object.keys(n.context).length>0&&e.jsxs("details",{className:"mt-1.5",children:[e.jsx("summary",{className:"text-[11px] text-muted-foreground/70 cursor-pointer hover:text-foreground",children:"Context"}),e.jsx("pre",{className:"mt-1 text-[11px] bg-header-bg p-1.5 rounded-sm overflow-x-auto text-muted-foreground",children:JSON.stringify(n.context,null,2)})]})]})]},a))})]})}const ne={pptx:["default","dark","minimal"],docx:["minimal","corporate","modern"]};function Xe({className:t}){var i;const r=E(l=>l.activeTab),s=E(l=>l.documentTypes),o=E(l=>l.documents),n=ue(l=>l.customThemes),a=x.useMemo(()=>{var c,u,f;if(!r||s[r]==="application/json+theme")return null;const l=o.find(m=>m.name===r);if(!(l!=null&&l.text))return null;let d;try{d=(u=(c=JSON.parse(l.text))==null?void 0:c.props)==null?void 0:u.theme}catch{return null}if(typeof d!="string"||!d||(f=ne[b])!=null&&f.includes(d))return null;for(const m of Object.values(n))if(m.valid&&m.name===d)return null;return d},[r,s,o,n]);return a?e.jsxs("div",{className:`flex items-start gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-2 ${t??""}`,children:[e.jsx(J,{className:"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0 text-xs leading-relaxed",children:[e.jsxs("span",{className:"font-medium text-warning",children:["Theme"," ",e.jsx("code",{className:"bg-warning/20 px-1 py-0.5 rounded-sm text-warning",children:a})," ","is not available."]})," ",e.jsxs("span",{className:"text-warning/80",children:["Add it as a custom theme or use a built-in theme (",(i=ne[b])==null?void 0:i.join(", "),"). The renderer will fall back to a default."]})]})]}):null}const Ye=8*1024*1024;function re(t){return Array.isArray(t)?t:[]}function Qe(t,r){var a;let s=[];if(typeof t=="string"&&t.length>0)try{const i=JSON.parse(t);s=re((a=i==null?void 0:i.props)==null?void 0:a.fontRegistry)}catch{return[]}const o=[];for(const i of Object.values(r??{}))o.push(...re(i==null?void 0:i.fontRegistry));const n=new Map;for(const i of[...o,...s])i&&typeof i.family=="string"&&n.set(i.family.toLowerCase(),i);return[...n.values()]}function Ze(t,r,s){const o=[{family:t,cssWeight:r,cssStyle:s?"italic":"normal"}],n=ke[r];return r!==400&&r!==700&&n&&o.push({family:`${t} ${n}${s?" Italic":""}`,cssWeight:400,cssStyle:"normal"}),o}const et=/^(?:data:[a-z0-9.+-]+\/[a-z0-9.+-]+;base64,)?[A-Za-z0-9+/=\s]+$/i;function tt(t){return et.test(t)?t.startsWith("data:")?t:`data:font/ttf;base64,${t}`:null}function xe(t){const r=[];for(const s of t.sources??[]){if(s.kind==="safe"||s.kind==="file"||s.kind==="google")continue;const o="italic"in s?!!s.italic:!1,n="weight"in s&&s.weight?s.weight:400;if(s.kind==="data"){const a=tt(s.data);if(!a)continue;r.push({family:t.family,weight:n,italic:o,url:a});continue}_e(s.url)&&r.push({family:t.family,weight:n,italic:o,url:s.url,variable:s.kind==="variable"})}return r}function st(t,r,s){const o=new Map;for(const i of r)for(const l of xe(i)){const d=l.family.toLowerCase();let c=o.get(d);c||o.set(d,c=new Set),c.add(l.weight)}const n=[],a=new Set;for(const i of t){if(Ee(i))continue;const l=i.toLowerCase();if(a.has(l))continue;const d=Re.find(m=>m.family.toLowerCase()===l);if(!d)continue;a.add(l);const c=o.get(l),u=new Set([400,700,...s]),f=d.weights.filter(m=>u.has(m)&&!(c!=null&&c.has(m)));f.length!==0&&n.push({family:d.family,weights:f,italics:d.hasItalic})}return n}function pe(t,r,s){const o=[...new Set(r)].sort((a,i)=>a-i),n=s?`ital,wght@${[...o.map(a=>`0,${a}`),...o.map(a=>`1,${a}`)].join(";")}`:`wght@${o.join(";")}`;return`https://fonts.googleapis.com/css2?family=${encodeURIComponent(t)}:${n}&display=swap`}const G=new Map,nt=3e3;async function rt(t,r,s,o=fetch,n=nt){const a=pe(t,r,s),i=G.get(a);if(i)return i;const l=(async()=>{const d=new AbortController;let c;const u=new Promise((f,m)=>{c=setTimeout(()=>{d.abort(),m(new Error(`Google Fonts CSS timed out after ${n}ms`))},n)});try{const f=await Promise.race([o(a,{signal:d.signal}),u]);if(!f.ok)throw new Error(`Google Fonts CSS ${f.status}`);const m=await Promise.race([f.text(),u]);return at(m,t)}finally{c&&clearTimeout(c)}})();return G.set(a,l),l.catch(()=>G.delete(a)),l}function at(t,r){var o,n,a,i,l,d;const s=[];for(const c of t.split("@font-face")){const u=(n=(o=/src:\s*([^;]+);/.exec(c))==null?void 0:o[1])==null?void 0:n.trim();if(!u)continue;const f=((a=/font-style:\s*(\w+)/.exec(c))==null?void 0:a[1])??"normal",m=Number(((i=/font-weight:\s*(\d+)/.exec(c))==null?void 0:i[1])??"400"),g=(d=(l=/unicode-range:\s*([^;]+);/.exec(c))==null?void 0:l[1])==null?void 0:d.trim(),w=g&&/^[Uu]\+[0-9A-Fa-f?,+\-Uu\s]*$/.test(g)?g:void 0;s.push({family:r,weight:Number.isFinite(m)?m:400,italic:f==="italic",src:u,...w?{unicodeRange:w}:{}})}return s}function ae(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/</g,"\\3c ")}function it(t,r=Ye){const s=new Set,o=[];let n=0,a=0;for(const i of t){const l=i.url?`url("${ae(i.url)}")`:i.src&&!i.src.includes("<")?i.src:void 0;if(l)for(const d of Ze(i.family,i.weight,i.italic)){const c=`${d.family}|${d.cssWeight}|${d.cssStyle}|${l}`;if(s.has(c))continue;s.add(c);const u=d.family!==i.family,f=i.variable&&u?`font-variation-settings:"wght" ${i.weight};`:"",m=`@font-face{font-family:"${ae(d.family)}";src:${l};font-weight:${d.cssWeight};font-style:${d.cssStyle};font-display:swap;`+f+(i.unicodeRange?`unicode-range:${i.unicodeRange};`:"")+"}";if(n+m.length>r){a++;continue}n+=m.length,o.push(m)}}return a>0&&console.warn(`Preview fonts: dropped ${a} @font-face rule(s) over the ${r}-byte budget.`),o.join(`
|
|
3
|
+
`)}function ie(t){const r=new Set,s=o=>{if(!(!o||typeof o!="object")){if(Array.isArray(o)){for(const n of o)s(n);return}for(const[n,a]of Object.entries(o))n==="fontWeight"&&typeof a=="number"?r.add(a):s(a)}};return s(t),r}async function ot(t,r,s){const o=Qe(t,r);let n;if(typeof t=="string"&&t.length>0)try{n=JSON.parse(t)}catch{n=void 0}const a=new Set,i=new Set;if(n!==void 0){for(const c of te(n))a.add(c);for(const c of ie(n))i.add(c)}for(const c of Object.values(r??{})){for(const u of te(c))a.add(u);for(const u of ie(c))i.add(u)}const l=[];for(const c of o)l.push(...xe(c));const d=[];for(const c of st(a,o,i))try{l.push(...await rt(c.family,c.weights,c.italics,(s==null?void 0:s.fetchImpl)??fetch,s==null?void 0:s.googleTimeoutMs))}catch{d.push(pe(c.family,c.weights,c.italics))}return{css:it(l,s==null?void 0:s.maxBytes),googleHrefs:d}}async function ct(t,r,s){const o=await Ce(()=>import("./docx-preview-DQa8jhzH.js"),__vite__mapDeps([0,1])),n=document.createElement("body"),a=document.createElement("head"),i=o.renderAsync(t,n,a,{inWrapper:!0}),l=new Promise((u,f)=>{setTimeout(()=>{f(new Error("DocxJS renderAsync timed out after 10 seconds"))},1e4)});await Promise.race([i,l]);try{const{css:u,googleHrefs:f}=await ot(r,s);for(const m of f){const g=document.createElement("link");g.rel="stylesheet",g.href=m,a.appendChild(g)}if(u){const m=document.createElement("style");m.textContent=u,a.appendChild(m)}}catch(u){console.warn("Preview font injection failed; using host fonts",u)}const d=document.createElement("link");d.rel="stylesheet",d.href=`${Le.basePath}/css/preview/docxjs.css`,a.appendChild(d);const c=document.createElement("html");return c.appendChild(a),c.appendChild(n),{iframeSrcDoc:c.outerHTML}}async function lt(t,r,s,o){const n=typeof s=="string"&&s.length>0;let a;if(n){let d;try{d=JSON.parse(s)}catch(u){throw new Error(`Invalid JSON document: ${u.message}`)}const c={jsonDefinition:d,customThemes:o??{},options:{sourceName:t}};a=await fetch(H.preview.libreofficeFromJson,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)})}else{const d=new FormData,c=b==="pptx"?".pptx":".docx";d.append("file",r,`${t}${c}`),a=await fetch(H.preview.libreoffice,{method:"POST",body:d})}if(!a.ok){let d=`LibreOffice preview failed (${a.status})`;try{const c=await a.json();c&&typeof c=="object"&&typeof c.error=="string"&&(d=c.error)}catch{}throw new Error(d)}const i=await a.blob();if(!i.size)throw new Error("LibreOffice preview returned an empty PDF");const l=URL.createObjectURL(i);return{iframeSrc:l,cleanup:()=>URL.revokeObjectURL(l)}}async function dt(t,r,s=b==="docx"?"docxjs":"LibreOffice",o,n,a){try{if(!r||r.size===0)throw new Error("Invalid or empty document blob");let i;return b==="docx"&&s==="docxjs"?i=await ct(r,n,a):i=await lt(t,r,n,a),{status:"success",name:t,payload:i}}catch(i){const l=i instanceof Error?i.message:String(i);return{status:"error",name:t,payload:new Error(l)}}}const I=x.forwardRef(({className:t,value:r,...s},o)=>e.jsx(me,{ref:o,className:S("relative h-4 w-full overflow-hidden rounded-full bg-secondary",t),...s,children:e.jsx(Pe,{className:"h-full w-full flex-1 bg-primary transition-all",style:{transform:`translateX(-${100-(r||0)}%)`}})}));I.displayName=me.displayName;const oe={"dynamic-context":"depends on render-time context","bookmark-id":"carries a bookmark id","revision-ids":"carries revision ids"};function q(t){if(t===0)return"0 B";const r=1024,s=["B","KB","MB","GB"],o=Math.floor(Math.log(t)/Math.log(r));return parseFloat((t/Math.pow(r,o)).toFixed(2))+" "+s[o]}function ut(){const[t,r]=x.useState(null),[s,o]=x.useState(!0),[n,a]=x.useState(null);if(x.useEffect(()=>{const d=new AbortController,c=async()=>{try{const m=await fetch(H.cacheStats,{signal:d.signal});if(!m.ok)throw new Error("Failed to fetch cache stats");const g=await m.json();d.signal.aborted||(r(g.data),a(null))}catch(m){d.signal.aborted||(m instanceof Error&&m.name!=="AbortError"?a(m.message):(!(m instanceof Error)||m.name!=="AbortError")&&a("Failed to load cache stats"))}finally{d.signal.aborted||o(!1)}};c();const u=setInterval(c,5e3),f=()=>c();return window.addEventListener("cache:cleared",f),()=>{d.abort(),clearInterval(u),window.removeEventListener("cache:cleared",f)}},[]),s)return e.jsx("div",{className:"flex items-center justify-center p-8",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-primary"})});if(n)return e.jsxs("div",{className:"text-destructive p-4",children:["Error loading cache metrics: ",n]});if(!t)return null;const{document:i}=t,l=i.hitRate*100;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-6 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Hit Rate"})," ",e.jsxs("span",{className:"font-semibold text-base",children:[l.toFixed(1),"%"]}),e.jsxs("span",{className:"text-muted-foreground ml-1",children:["(",i.hits," hits / ",i.misses," misses)"]})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Size"})," ",e.jsx("span",{className:"font-semibold",children:q(i.size)}),e.jsxs("span",{className:"text-muted-foreground ml-1",children:["(",i.itemCount," items)"]})]}),e.jsx(Fe,{variant:i.enabled?"default":"secondary",children:i.enabled?"Enabled":"Disabled"})]}),e.jsx(I,{value:l,className:"h-2","aria-label":"Cache hit rate"}),b==="docx"&&t.components&&e.jsx(mt,{data:t.components}),t.rasterizer&&e.jsx(ft,{data:t.rasterizer})]})}function mt({data:t}){const r=t.bypassedComponents??[];return t.componentStats.length===0&&r.length===0?null:e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"text-sm font-medium",children:"Module Breakdown"}),e.jsxs("div",{className:"space-y-1",children:[t.componentStats.map(s=>{const o=(s.hitRate||0)*100,n=s.totalRequests||s.hits+s.misses,a=s.memoryUsage||s.entries*s.avgSize||0;return e.jsxs("div",{className:"px-3 py-1.5 text-sm",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"font-medium",children:s.type}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsxs("span",{children:[o.toFixed(0),"% hit"]}),e.jsxs("span",{children:[n," req"]}),e.jsx("span",{children:q(a)})]})]}),e.jsx(I,{value:o,className:"h-1.5"})]},s.type)}),r.map(s=>e.jsx("div",{className:"px-3 py-1.5 text-sm",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"font-medium text-muted-foreground",children:s.type}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsxs("span",{children:["uncached by design",oe[s.reason]?` — ${oe[s.reason]}`:""]}),e.jsxs("span",{children:[s.renders," renders"]})]})]})},`bypass-${s.type}`))]})]})}function ft({data:t}){const r=t.diskHits+t.diskMisses;if(r+t.dedupedRequests+t.rendered+t.entries===0)return null;const o=t.hitRate*100,n=t.prepass?t.prepass.collected-t.prepass.unique:t.dedupedRequests;return e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"text-sm font-medium",children:"Visual Rasterizer"}),e.jsxs("div",{className:"px-3 py-1.5 text-sm space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Disk cache"}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx("span",{children:r>0?`${o.toFixed(0)}% hit`:"no lookups"}),e.jsxs("span",{children:["(",t.diskHits," hits / ",t.diskMisses," misses)"]}),e.jsxs("span",{children:[t.entries," PNGs, ",q(t.bytes)]})]})]}),e.jsx(I,{value:o,className:"h-1.5","aria-label":"Rasterizer disk cache hit rate"}),e.jsxs("div",{className:"flex items-center justify-between text-xs text-muted-foreground",children:[e.jsxs("span",{children:[t.rendered," rendered",t.failed>0?`, ${t.failed} failed`:""]}),e.jsxs("span",{children:[n," duplicate visual",n===1?"":"s"," deduped",t.prepass?` (${t.prepass.collected} collected → ${t.prepass.unique} unique)`:""]})]})]})]})}const ht=x.memo(function({editTimestamp:r,debounceMs:s}){const[o,n]=x.useState(()=>Math.max(0,r+s-Date.now()));if(x.useEffect(()=>{let l;const d=()=>{const c=Math.max(0,r+s-Date.now());n(c),c<=0&&l!=null&&clearInterval(l)};return d(),l=setInterval(d,100),()=>{l!=null&&clearInterval(l)}},[r,s]),o<=0)return null;const a=(o/1e3).toFixed(1),i=Math.min(100,o/s*100);return e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-xs text-warning tabular-nums",children:[e.jsx("span",{className:"h-1 rounded-full bg-warning/60 transition-[width] duration-100",style:{width:`${Math.round(i*.4)}px`}}),a,"s"]})});function Et(){var D,ee;const{autoReload:t,renderingLibrary:r,saveDocumentDebounceWait:s,setSettings:o}=se(h=>h),{name:n,text:a,blob:i,isGenerating:l,generationProgress:d,generationStartedAt:c,cancelGeneration:u,globalError:f,cacheStatus:m,cacheHitRate:g,warnings:w,isRendering:j,isPreviewStale:R,editSequence:k,lastBuiltSequence:ge,editTimestamp:V,hasValidationErrors:we,setOutput:N}=Be(h=>h),y=E(h=>h.activeTab),K=E(h=>h.documentTypes),X=E(h=>{var p;return h.activeTab&&h.documentTypes[h.activeTab]!=="application/json+theme"?(p=h.documents.find(U=>U.name===h.activeTab))==null?void 0:p.text:void 0}),Y=ue(h=>h.customThemes),B=x.useMemo(()=>{const h={};for(const p of Object.values(Y))p.valid&&p.name&&p.parsed&&(h[p.name]=p.parsed);return h},[Y]),[C,ve]=x.useState(void 0),[je,ye]=x.useState(void 0),[be,P]=x.useState(!1),Q=A.useRef(null),$=x.useRef(null),z=x.useRef(!1),M=x.useCallback(()=>{$.current&&($.current(),$.current=null)},[]),L=x.useCallback(async(h,p,U,Se)=>{N({isRendering:!0,isPreviewStale:!1,globalError:void 0});try{const{status:F,payload:v}=await dt(h,p,r,void 0,U,Se);if(F!=="success")throw v instanceof Error?v:new Error(String(v));M(),ve(v.iframeSrc||void 0),ye(v.iframeSrcDoc||void 0),$.current=v.cleanup||null}catch(F){const v=F instanceof Error?F.message:String(F);let W=v;v.includes("Failed to fetch")?W="Network error: Unable to load required resources. Check if the server is running properly.":v.includes("timeout")&&(W="Render timeout: The rendering process took too long."),N({globalError:W})}finally{N({isRendering:!1})}},[N,M,r]),Ne=x.useRef({name:n,blob:i,text:a,doRender:L});x.useEffect(()=>{Ne.current={name:n,blob:i,text:a,doRender:L}});const _=x.useCallback(async()=>{z.current=!0,window.dispatchEvent(new CustomEvent("preview:flushAndBuild"))},[]);x.useEffect(()=>{i&&n&&t&&r==="docxjs"?L(n,i,a,B):i&&n&&z.current?(z.current=!1,L(n,i,a,B)):i&&n&&N({isPreviewStale:!0})},[i,n,a,B,t,r,L,N]),x.useEffect(()=>()=>{M()},[M]),x.useEffect(()=>{const h=()=>_(),p=()=>P(!0);return window.addEventListener("preview:manualRender",h),window.addEventListener("preview:showCacheMetrics",p),()=>{window.removeEventListener("preview:manualRender",h),window.removeEventListener("preview:showCacheMetrics",p)}},[_]);const Z=((ee=(D=se)==null?void 0:D.getState)==null?void 0:ee.call(D).useGlobalPreviewHeader)===!1;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex h-full flex-col",children:[Z&&e.jsx(Oe,{iframeRef:Q,displayReloadButton:!!C&&!((C==null?void 0:C.startsWith("blob:"))??!1),name:(n==null?void 0:n.trim())||"Preview",blob:i,autoReload:t,onToggleAutoReload:()=>o({autoReload:!t}),onManualRender:_,isGenerating:l,isRendering:j,onShowCacheMetrics:()=>P(!0),documentText:a,editorDocumentText:X,warnings:w,renderingLibrary:r,setRenderingLibrary:h=>o({renderingLibrary:h})}),!Z&&e.jsx($e,{}),b==="docx"&&r==="docxjs"&&e.jsxs("div",{className:"px-3 py-1.5 flex items-center gap-2 border-b bg-data-blue/10 text-xs text-data-blue",children:[e.jsx(de,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{children:"The docxjs renderer is not 100% representative of the actual .docx. Use LibreOffice for higher fidelity."})]}),(()=>{const h=(k??0)>(ge??0),p=(R||h)&&!l&&!j;return(m&&m!=="UNKNOWN"||p)&&e.jsxs("div",{className:`px-3 py-1.5 flex items-center justify-between border-b overflow-hidden ${p?"bg-warning/10":"bg-header-bg"}`,children:[e.jsx("div",{className:"flex items-center gap-2 min-w-0 truncate",children:m==="HIT"&&!p?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-success flex-shrink-0"}),e.jsx("span",{className:"text-xs text-muted-foreground truncate",children:"Cached"})]}):m==="MISS"&&!p?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-accent2 flex-shrink-0"}),e.jsxs("span",{className:"text-xs text-muted-foreground truncate",children:["Fresh ",ce.toLowerCase()]})]}):p?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"h-1.5 w-1.5 rounded-full bg-warning flex-shrink-0"}),e.jsx("span",{className:"text-xs text-warning truncate",children:"Outdated — click Run"}),V&&h&&!l&&!we&&t&&r==="docxjs"&&e.jsx(ht,{editTimestamp:V,debounceMs:s+200})]}):null}),!p&&g&&g!=="0.0%"&&e.jsxs("span",{className:"text-xs text-muted-foreground flex-shrink-0 ml-2",children:[g," hit rate"]})]})})(),e.jsx(Ke,{warnings:w,className:"mx-3 my-2"}),e.jsx(Xe,{className:"mx-3 my-2"}),f&&!l?e.jsx("div",{className:"flex-1 flex items-center justify-center p-6",children:e.jsxs("div",{className:"max-w-md rounded-sm border-l-4 border-l-destructive bg-destructive/10 px-4 py-3 text-sm text-destructive",children:[e.jsx("p",{className:"font-medium mb-1",children:"Generation failed"}),e.jsx("p",{className:"text-xs text-destructive/80 break-words",children:f})]})}):e.jsx(Ve,{ref:Q,isLoading:!!j,iframeSrc:C,iframeSrcDoc:je,isGenerating:(()=>{const h=t&&r==="docxjs",p=y&&n&&y!==n&&K[y]!=="application/json+theme";return!!l||!!(h&&p)})(),generationProgress:(()=>{const h=t&&r==="docxjs",p=y&&n&&y!==n&&K[y]!=="application/json+theme";return h&&p&&!l?{stage:"parsing",message:`Building preview for ${y}...`}:d})(),generationDocumentText:X??a,generationStartedAt:c,onCancelGeneration:u})]}),e.jsx(Me,{open:be,onOpenChange:P,children:e.jsxs(De,{className:"max-w-2xl",children:[e.jsx(Te,{children:e.jsx(Ae,{children:"Cache Performance"})}),e.jsx(ut,{})]})})]})}export{Et as Preview};
|
|
4
|
+
//# sourceMappingURL=preview-D3QYaLPp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","names":["FONT_URL_ALLOWLIST","isAllowedFontUrl","url","parsed","useElapsedSeconds","startedAt","fallbackStart","useState","start","now","setNow","useEffect","id","summarizeDocument","text","root","counts","stack","node","name","children","summary","key","singular","plural","count","entry","title","_b","_a","buildHints","hints","CheckIcon","jsx","DocumentGenerationLoader","className","currentStage","message","documentText","onCancel","stages","stageLabels","currentStageIndex","elapsed","useMemo","showHints","hintIndex","cn","jsxs","Spinner","label","stage","index","isActive","isCompleted","Button","GenerationOverlay","mode","PreviewLoading","renderingLibrary","getLibraryInfo","library","description","Skeleton","PreviewFrame","React","isLoading","iframeSrc","iframeSrcDoc","isGenerating","generationProgress","generationDocumentText","generationStartedAt","onCancelGeneration","ref","iframeLoaded","setIframeLoaded","handleIframeLoad","handleIframeError","iframeSandbox","hasContent","FORMAT_LABEL","PreviewFrameMemoized","WarningsPanel","warnings","isExpanded","setIsExpanded","ChevronRight","AlertTriangle","warning","Info","BUILTIN_THEMES","UnavailableThemeWarning","activeTab","useDocumentsStore","s","documentTypes","documents","customThemes","useThemesStore","missingThemeName","doc","d","themeName","_c","FORMAT","ct","DEFAULT_MAX_BYTES","asArray","v","extractFontRegistries","jsonText","docEntries","themeEntries","theme","byFamily","e","synthesizedFamilyNames","family","weight","italic","out","WEIGHT_LABELS","DATA_FONT_RE","dataUrlFor","raw","facesFromRegistryEntry","faces","source","googleFamiliesFor","referencedNames","registryEntries","referencedWeights","coveredWeights","face","set","emitted","isSafeFont","lower","match","POPULAR_GOOGLE_FONTS","f","already","wanted","weights","w","buildGoogleCss2Href","italics","sorted","b","axis","googleFaceCache","GOOGLE_CSS_TIMEOUT_MS","fetchGoogleFacesRewritten","fetchImpl","timeoutMs","href","cached","pending","controller","timer","expiry","_","reject","res","parseGoogleCss","css","block","src","style","_d","rawRange","_f","_e","unicodeRange","escapeCssString","renderFontFaceCss","maxBytes","seen","rules","bytes","dropped","n","isSynthetic","variation","rule","collectReferencedWeights","visit","item","k","buildPreviewFontAssets","opts","entries","parsedDoc","names","collectFontNamesFromDocx","googleHrefs","g","renderDocxWithDocxJS","blob","docx_preview","__vitePreload","bodyEl","headEl","renderPromise","timeoutPromise","gf","fontStyleEl","err","overrideStyleEl","env","htmlEl","renderWithLibreOffice","useJsonPath","response","jsonDefinition","body","API_ENDPOINTS","formData","ext","json","pdfBlob","objectUrl","renderDocument","_baseUrl","payload","error","errorMessage","Progress","React.forwardRef","value","props","ProgressPrimitive.Root","ProgressPrimitive.Indicator","BYPASS_REASON_LABELS","formatBytes","sizes","i","CacheMetrics","stats","setStats","loading","setLoading","setError","fetchData","data","interval","handleCacheCleared","hitRatePct","Badge","ComponentBreakdown","RasterizerBreakdown","bypassed","stat","hitRate","requests","memory","lookups","dedupeSaved","DebounceCountdown","memo","editTimestamp","debounceMs","remaining","setRemaining","tick","r","secs","pct","Preview","autoReload","saveDocumentDebounceWait","setSettings","useSettingsStore","state","cancelGeneration","globalError","cacheStatus","cacheHitRate","isRendering","isPreviewStale","editSequence","lastBuiltSequence","hasValidationErrors","setOutput","useOutputStore","editorDocumentText","customThemesMap","themesForServer","setIframeSrc","setIframeSrcDoc","showCacheMetrics","setShowCacheMetrics","iframeRef","renderCleanupRef","useRef","pendingManualRenderRef","cleanupRenderedPreview","useCallback","doRender","docName","docBlob","docText","themes","status","displayMessage","manualRenderRef","handleManualRender","onManual","onShowCache","localHeaderVisible","Fragment","PreviewHeaderMemoized","lib","Separator","InfoIcon","hasUnsyncedEdits","isStale","willAutoBuild","isSwitchingDoc","Dialog","DialogContent","DialogHeader","DialogTitle"],"ignoreList":[],"sources":["../../../../shared/dist/chunk-FDSJYZ5W.js","../../../src/client/components/ui/loading-states.tsx","../../../src/client/components/playground/preview-frame.tsx","../../../src/client/components/playground/warnings-panel.tsx","../../../src/client/components/playground/unavailable-theme-warning.tsx","../../../src/client/lib/preview-fonts.ts","../../../src/client/lib/render.ts","../../../src/client/components/ui/progress.tsx","../../../src/client/components/cache-metrics.tsx","../../../src/client/components/playground/preview.tsx"],"sourcesContent":["// src/fonts/sources/url-allowlist.ts\nvar FONT_URL_ALLOWLIST = [\n \"fonts.gstatic.com\",\n \"fonts.googleapis.com\",\n \"cdn.jsdelivr.net\"\n];\nfunction isAllowedFontUrl(url) {\n let parsed;\n try {\n parsed = new URL(url);\n } catch {\n return false;\n }\n if (parsed.protocol !== \"https:\") return false;\n return FONT_URL_ALLOWLIST.includes(parsed.hostname.toLowerCase());\n}\n\n// src/fonts/sources/format.ts\nfunction detectFontFormat(buf) {\n if (buf.length < 4) return \"unknown\";\n const b0 = buf[0], b1 = buf[1], b2 = buf[2], b3 = buf[3];\n if (b0 === 0 && b1 === 1 && b2 === 0 && b3 === 0 || b0 === 116 && b1 === 114 && b2 === 117 && b3 === 101 || b0 === 116 && b1 === 121 && b2 === 112 && b3 === 49) {\n return \"ttf\";\n }\n if (b0 === 79 && b1 === 84 && b2 === 84 && b3 === 79) return \"otf\";\n if (b0 === 119 && b1 === 79 && b2 === 70 && b3 === 70) return \"woff\";\n if (b0 === 119 && b1 === 79 && b2 === 70 && b3 === 50) return \"woff2\";\n if (buf.length >= 36 && buf[34] === 76 && buf[35] === 80) return \"eot\";\n if (b0 === 128 && b1 === 1) return \"pfb\";\n if (buf.length >= 14 && buf.slice(0, 14).toString(\"ascii\") === \"%!PS-AdobeFont\") {\n return \"pfb\";\n }\n return \"unknown\";\n}\n\nexport {\n FONT_URL_ALLOWLIST,\n isAllowedFontUrl,\n detectFontFormat\n};\n//# sourceMappingURL=chunk-FDSJYZ5W.js.map","import { useEffect, useMemo, useState } from 'react';\nimport { cn } from '@/lib/utils';\nimport { Spinner } from './spinner';\nimport { Skeleton } from './skeleton';\nimport { Button } from './button';\n\ninterface LoadingOverlayProps {\n isLoading: boolean;\n children: React.ReactNode;\n message?: string;\n className?: string;\n}\n\nexport function LoadingOverlay({\n isLoading,\n children,\n message = 'Loading...',\n className,\n}: LoadingOverlayProps) {\n return (\n <div className={cn('relative', className)}>\n {children}\n {isLoading && (\n <div className=\"absolute inset-0 bg-background/80 backdrop-blur-sm flex items-center justify-center z-50\">\n <div className=\"flex flex-col items-center gap-2\">\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n </div>\n </div>\n )}\n </div>\n );\n}\n\ninterface DocumentGenerationLoaderProps {\n className?: string;\n currentStage?: 'parsing' | 'building' | 'rendering' | 'finalizing';\n message?: string;\n /** Source JSON of the document being built — drives the content summary. */\n documentText?: string;\n /** Date.now() when the build started — drives the elapsed timer. */\n startedAt?: number;\n /** When provided, renders a Cancel button that aborts the build. */\n onCancel?: () => void;\n}\n\n/** Ticks every 100ms and returns whole elapsed seconds since `startedAt`. */\nfunction useElapsedSeconds(startedAt?: number): number {\n // Freeze the fallback start on first render so a caller that never passes\n // `startedAt` still gets a stable timer instead of one reset per render.\n const [fallbackStart] = useState(() => Date.now());\n const start = startedAt ?? fallbackStart;\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 100);\n return () => clearInterval(id);\n }, []);\n return Math.max(0, (now - start) / 1000);\n}\n\ninterface DocumentSummary {\n title?: string;\n counts: { label: string; count: number }[];\n visualCount: number;\n imageCount: number;\n}\n\n/**\n * Walk a JTO document tree and count the component types worth narrating.\n * Best-effort: any parse/shape surprise returns null and the loader simply\n * omits the summary row.\n */\nfunction summarizeDocument(text?: string): DocumentSummary | null {\n if (!text) return null;\n try {\n const root = JSON.parse(text);\n if (!root || typeof root !== 'object') return null;\n const counts = new Map<string, number>();\n const stack: unknown[] = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n if (!node || typeof node !== 'object') continue;\n const { name, children } = node as {\n name?: unknown;\n children?: unknown;\n };\n if (typeof name === 'string') {\n counts.set(name, (counts.get(name) ?? 0) + 1);\n }\n if (Array.isArray(children)) stack.push(...children);\n }\n // Ordered by how much each type usually tells the user about build cost.\n const interesting: [key: string, singular: string, plural: string][] = [\n ['slide', 'slide', 'slides'],\n ['section', 'section', 'sections'],\n ['visual', 'visual', 'visuals'],\n ['chart', 'chart', 'charts'],\n ['image', 'image', 'images'],\n ['table', 'table', 'tables'],\n ['shape', 'shape', 'shapes'],\n ['paragraph', 'paragraph', 'paragraphs'],\n ];\n const summary = interesting\n .map(([key, singular, plural]) => {\n const count = counts.get(key) ?? 0;\n return { label: count === 1 ? singular : plural, count };\n })\n .filter((entry) => entry.count > 0)\n .slice(0, 5);\n const title = (root as { props?: { metadata?: { title?: unknown } } }).props\n ?.metadata?.title;\n return {\n title: typeof title === 'string' ? title : undefined,\n counts: summary,\n visualCount: (counts.get('visual') ?? 0) + (counts.get('chart') ?? 0),\n imageCount: counts.get('image') ?? 0,\n };\n } catch {\n return null;\n }\n}\n\n/** Rotating context lines shown once a build takes more than a moment. */\nfunction buildHints(summary: DocumentSummary | null): string[] {\n const hints: string[] = [];\n if (summary && summary.visualCount > 0) {\n hints.push(\n `${summary.visualCount} visual${summary.visualCount === 1 ? '' : 's'} in this document ${\n summary.visualCount === 1 ? 'is' : 'are'\n } rasterized on first build — later builds reuse the cached renders.`\n );\n }\n if (summary && summary.imageCount > 3) {\n hints.push(\n 'Large embedded images dominate build time — downscaling them speeds up iteration.'\n );\n }\n hints.push(\n 'Re-running an unchanged document is served from the cache almost instantly.',\n 'Generation warnings, if any, will appear above the preview when the build completes.'\n );\n return hints;\n}\n\nconst CheckIcon = () => (\n <svg\n className=\"h-3.5 w-3.5 text-success\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M3 8.5L6.5 12L13 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport function DocumentGenerationLoader({\n className,\n currentStage = 'parsing',\n message,\n documentText,\n startedAt,\n onCancel,\n}: DocumentGenerationLoaderProps) {\n const stages = ['parsing', 'building', 'rendering', 'finalizing'] as const;\n const stageLabels: Record<(typeof stages)[number], string> = {\n parsing: 'Validating JSON',\n building: 'Building structure',\n rendering: 'Rendering content',\n finalizing: 'Finalizing document',\n };\n\n const currentStageIndex = stages.indexOf(currentStage);\n const elapsed = useElapsedSeconds(startedAt);\n const summary = useMemo(\n () => summarizeDocument(documentText),\n [documentText]\n );\n const hints = useMemo(() => buildHints(summary), [summary]);\n // Hints appear only for builds long enough to leave the user wondering,\n // then rotate so a long rasterization pass keeps saying something new.\n const showHints = elapsed > 3;\n const hintIndex = Math.floor(Math.max(0, elapsed - 3) / 5) % hints.length;\n\n return (\n <div className={cn('p-6 max-w-lg mx-auto space-y-5', className)}>\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3 min-w-0\">\n <Spinner size=\"md\" />\n <div className=\"space-y-0.5 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {summary?.title\n ? `Generating “${summary.title}”`\n : 'Generating document'}\n </p>\n {/* The live region covers only the stage message — putting it on\n the container would re-announce the whole loader every 100ms\n elapsed-timer tick. */}\n <p\n className=\"text-xs text-muted-foreground truncate\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {message || `${stageLabels[currentStage]}...`}\n </p>\n </div>\n </div>\n <span\n className=\"shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums\"\n aria-hidden=\"true\"\n >\n {elapsed.toFixed(1)}s\n </span>\n </div>\n\n {summary && summary.counts.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\" aria-label=\"Document contents\">\n {summary.counts.map(({ label, count }) => (\n <span\n key={label}\n className=\"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs text-muted-foreground\"\n >\n <span className=\"font-medium text-foreground tabular-nums\">\n {count}\n </span>\n {label}\n </span>\n ))}\n </div>\n )}\n\n <div className=\"space-y-3\">\n {stages.map((stage, index) => {\n const isActive = index === currentStageIndex;\n const isCompleted = index < currentStageIndex;\n return (\n <div key={stage} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between text-xs\">\n <span\n className={cn(\n isActive\n ? 'text-primary font-medium'\n : isCompleted\n ? 'text-muted-foreground'\n : 'text-muted-foreground/60'\n )}\n >\n {stageLabels[stage]}\n </span>\n {isCompleted ? (\n <CheckIcon />\n ) : isActive ? (\n <Spinner size=\"sm\" className=\"h-3.5 w-3.5\" />\n ) : (\n <span className=\"h-3.5 w-3.5 rounded-full border border-muted-foreground/40\" />\n )}\n </div>\n <div className=\"w-full bg-secondary rounded-full h-1.5 overflow-hidden\">\n {isCompleted ? (\n <div className=\"h-full w-full rounded-full bg-success\" />\n ) : isActive ? (\n // Honest indeterminate sweep — we have no real progress\n // signal within a stage, so don't fake a full bar.\n <div className=\"h-full w-2/5 rounded-full bg-primary animate-progress-indeterminate\" />\n ) : null}\n </div>\n </div>\n );\n })}\n </div>\n\n <div className=\"flex items-center justify-between gap-3 min-h-8\">\n <p\n className={cn(\n 'text-xs text-muted-foreground/80 italic transition-opacity duration-500',\n showHints ? 'opacity-100' : 'opacity-0'\n )}\n >\n {hints[hintIndex]}\n </p>\n {onCancel && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onCancel}\n className=\"shrink-0\"\n >\n Cancel\n </Button>\n )}\n </div>\n </div>\n );\n}\n\ninterface GenerationOverlayProps {\n mode: 'generating' | 'rendering';\n message?: string;\n startedAt?: number;\n onCancel?: () => void;\n className?: string;\n}\n\n/**\n * Compact card for the overlay shown on top of an existing preview while a\n * rebuild or re-render is in flight.\n */\nexport function GenerationOverlay({\n mode,\n message,\n startedAt,\n onCancel,\n className,\n}: GenerationOverlayProps) {\n const elapsed = useElapsedSeconds(startedAt);\n return (\n <div\n className={cn(\n 'flex flex-col items-center gap-2 rounded-md border bg-background/95 px-6 py-4 shadow-sm',\n className\n )}\n >\n <div className=\"flex items-center gap-2\">\n <Spinner size=\"md\" />\n {/* Live region on the label only — the elapsed badge ticks every\n 100ms and must not retrigger screen-reader announcements. */}\n <p className=\"text-sm font-medium\" role=\"status\" aria-live=\"polite\">\n {mode === 'generating' ? 'Generating' : 'Rendering'}\n </p>\n <span\n className=\"rounded-full bg-secondary px-2 py-0.5 text-xs text-muted-foreground tabular-nums\"\n aria-hidden=\"true\"\n >\n {elapsed.toFixed(1)}s\n </span>\n </div>\n {message && (\n <p className=\"max-w-xs text-center text-xs text-muted-foreground truncate\">\n {message}\n </p>\n )}\n {mode === 'generating' && onCancel && (\n <Button variant=\"outline\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n )}\n </div>\n );\n}\n\ninterface PreviewLoadingProps {\n renderingLibrary?: string;\n className?: string;\n}\n\nexport function PreviewLoading({\n renderingLibrary,\n className,\n}: PreviewLoadingProps) {\n const getLibraryInfo = (library?: string) => {\n switch (library) {\n case 'LibreOffice':\n return {\n name: 'LibreOffice',\n description: 'Converting document to PDF locally...',\n };\n case 'Office':\n return {\n name: 'Microsoft Office',\n description: 'Uploading file and loading Office viewer...',\n };\n case 'Docs':\n return {\n name: 'Google Docs',\n description: 'Uploading file and loading Docs viewer...',\n };\n default:\n return { name: 'Default', description: 'Processing document...' };\n }\n };\n\n const { name, description } = getLibraryInfo(renderingLibrary);\n\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center h-full p-8 space-y-4',\n className\n )}\n >\n <Spinner size=\"lg\" />\n <div className=\"text-center space-y-2\">\n <p className=\"text-sm font-medium\">Rendering Preview</p>\n <p className=\"text-xs text-muted-foreground\">Using {name} renderer</p>\n <p className=\"text-xs text-muted-foreground/80\">{description}</p>\n </div>\n\n <div className=\"w-full max-w-md space-y-3\">\n <Skeleton className=\"h-16 w-full\" />\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n <Skeleton className=\"h-12 w-full\" />\n </div>\n </div>\n );\n}\n\ninterface InlineLoaderProps {\n message?: string;\n size?: 'sm' | 'md';\n className?: string;\n}\n\nexport function InlineLoader({\n message = 'Loading...',\n size = 'sm',\n className,\n}: InlineLoaderProps) {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n <Spinner size={size} />\n <span className=\"text-sm text-muted-foreground\">{message}</span>\n </div>\n );\n}\n\ninterface FileOperationLoaderProps {\n operation: 'upload' | 'download' | 'save' | 'delete';\n fileName?: string;\n progress?: number;\n className?: string;\n}\n\nexport function FileOperationLoader({\n operation,\n fileName,\n progress,\n className,\n}: FileOperationLoaderProps) {\n const operationLabels = {\n upload: 'Uploading',\n download: 'Downloading',\n save: 'Saving',\n delete: 'Deleting',\n };\n\n return (\n <div\n className={cn(\n 'flex items-center gap-3 p-3 border rounded-sm bg-header-bg',\n className\n )}\n >\n <Spinner size=\"sm\" />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {operationLabels[operation]} {fileName && `\"${fileName}\"`}\n </p>\n {progress !== undefined && (\n <div className=\"mt-1\">\n <div className=\"flex justify-between text-xs mb-1\">\n <span>{progress}%</span>\n <span className=\"text-muted-foreground\">\n {progress < 100 ? 'In progress...' : 'Complete'}\n </span>\n </div>\n <div className=\"w-full bg-secondary rounded-full h-1.5\">\n <div\n className=\"bg-primary h-1.5 rounded-full transition-all duration-300\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState } from 'react';\nimport {\n DocumentGenerationLoader,\n GenerationOverlay,\n PreviewLoading,\n} from '../ui/loading-states';\nimport { FORMAT_LABEL } from '../../lib/env';\n\nconst PreviewFrame = React.forwardRef<\n HTMLIFrameElement,\n {\n isLoading: boolean;\n iframeSrc?: string;\n iframeSrcDoc?: string;\n isGenerating?: boolean;\n generationProgress?: {\n stage: 'parsing' | 'building' | 'rendering' | 'finalizing';\n message?: string;\n };\n /** Source JSON being built — feeds the loader's content summary. */\n generationDocumentText?: string;\n /** Date.now() when the build started — feeds the elapsed timer. */\n generationStartedAt?: number;\n /** Aborts the in-flight build; renders a Cancel button when present. */\n onCancelGeneration?: () => void;\n }\n>(\n (\n {\n isLoading,\n iframeSrc,\n iframeSrcDoc,\n isGenerating,\n generationProgress,\n generationDocumentText,\n generationStartedAt,\n onCancelGeneration,\n },\n ref\n ) => {\n const [iframeLoaded, setIframeLoaded] = useState(false);\n\n // Reset iframe loaded state when content changes\n useEffect(() => {\n setIframeLoaded(false);\n }, [iframeSrc, iframeSrcDoc]);\n\n // Handle iframe load event\n const handleIframeLoad = () => {\n setIframeLoaded(true);\n };\n\n // Handle iframe errors\n const handleIframeError = () => {\n console.warn('Iframe failed to load content');\n setIframeLoaded(false);\n };\n\n // PDF blob URLs and remote viewers can be blocked by Chromium-based browsers\n // when loaded in a sandboxed iframe. Keep sandbox only for srcDoc-based preview.\n const iframeSandbox = iframeSrcDoc\n ? 'allow-scripts allow-popups allow-forms'\n : undefined;\n\n const hasContent = Boolean(iframeSrc || iframeSrcDoc);\n\n // Full-screen loaders only when no existing content\n if (isGenerating && !hasContent) {\n return (\n <div className=\"grow\">\n <DocumentGenerationLoader\n currentStage={generationProgress?.stage}\n message={generationProgress?.message}\n documentText={generationDocumentText}\n startedAt={generationStartedAt}\n onCancel={onCancelGeneration}\n />\n </div>\n );\n }\n\n if (isLoading && !hasContent) {\n return (\n <div className=\"grow\">\n <PreviewLoading renderingLibrary=\"LibreOffice\" />\n </div>\n );\n }\n\n if (hasContent) {\n return (\n <div className=\"h-full w-full relative bg-white\">\n {/* Loading overlay */}\n {!iframeLoaded && (\n <div className=\"absolute inset-0 bg-muted/80 flex items-center justify-center z-10\">\n <div className=\"text-center\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-foreground mx-auto mb-2\"></div>\n <p className=\"text-sm text-muted-foreground\">\n Loading preview...\n </p>\n </div>\n </div>\n )}\n {/* Generating/Rendering overlay on top of existing content */}\n {(isGenerating || isLoading) && (\n <div className=\"absolute inset-0 bg-background/60 backdrop-blur-[2px] flex items-center justify-center z-20 transition-opacity duration-200\">\n <GenerationOverlay\n mode={isGenerating ? 'generating' : 'rendering'}\n message={isGenerating ? generationProgress?.message : undefined}\n startedAt={isGenerating ? generationStartedAt : undefined}\n onCancel={isGenerating ? onCancelGeneration : undefined}\n />\n </div>\n )}\n {/* Key forces remount when switching between srcDoc (sandboxed) and\n src (blob URL, no sandbox) to avoid stale sandbox race condition */}\n <iframe\n key={iframeSrcDoc ? 'srcdoc' : 'src'}\n ref={ref}\n className=\"w-full h-full border-0\"\n style={{\n backgroundColor: 'white',\n // Fade in after load to prevent flash\n opacity: iframeLoaded ? 1 : 0,\n transition: 'opacity 0.2s ease-in-out',\n }}\n src={iframeSrc}\n srcDoc={iframeSrcDoc}\n onLoad={handleIframeLoad}\n onError={handleIframeError}\n // Security: sandbox srcDoc to prevent XSS from rendered HTML.\n // Blob URLs (src) must NOT be sandboxed without allow-same-origin.\n sandbox={iframeSandbox}\n // Accessibility\n title=\"Document preview\"\n aria-label={`Preview of rendered ${FORMAT_LABEL.toLowerCase()}`}\n />\n </div>\n );\n }\n return null;\n }\n);\n\nPreviewFrame.displayName = 'PreviewFrame';\nexport const PreviewFrameMemoized = React.memo(PreviewFrame);\n","import React from 'react';\nimport { AlertTriangle, Info, ChevronRight } from 'lucide-react';\nimport type { GenerationWarning } from '../../store/output-store';\n\ninterface WarningsPanelProps {\n warnings: GenerationWarning[] | null | undefined;\n className?: string;\n}\n\nexport function WarningsPanel({ warnings, className }: WarningsPanelProps) {\n const [isExpanded, setIsExpanded] = React.useState(false);\n\n if (!warnings || warnings.length === 0) {\n return null;\n }\n\n return (\n <div className={className}>\n <button\n type=\"button\"\n onClick={() => setIsExpanded(!isExpanded)}\n className=\"flex w-full items-center gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-1.5 text-left transition-colors hover:bg-warning/20\"\n >\n <ChevronRight\n className={`h-3.5 w-3.5 text-warning transition-transform flex-shrink-0 ${isExpanded ? 'rotate-90' : ''}`}\n />\n <AlertTriangle className=\"h-3.5 w-3.5 text-warning flex-shrink-0\" />\n <span className=\"text-xs font-medium text-warning\">\n {warnings.length} warning{warnings.length !== 1 ? 's' : ''}\n </span>\n </button>\n\n {isExpanded && (\n <div className=\"mt-1.5 space-y-1.5\">\n {warnings.map((warning, index) => (\n <div\n key={index}\n className=\"flex items-start gap-2 rounded-sm border bg-card px-3 py-2\"\n >\n {warning.severity === 'info' ? (\n <Info className=\"h-3.5 w-3.5 mt-0.5 text-data-blue flex-shrink-0\" />\n ) : (\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <code className=\"text-[11px] font-medium text-warning bg-warning/15 px-1 py-0.5 rounded-sm\">\n {warning.component}\n </code>\n {warning.severity === 'info' && (\n <span className=\"text-[10px] uppercase tracking-wide text-data-blue font-medium\">\n info\n </span>\n )}\n </div>\n <p className=\"mt-0.5 text-xs text-muted-foreground leading-relaxed\">\n {warning.message}\n </p>\n {warning.context && Object.keys(warning.context).length > 0 && (\n <details className=\"mt-1.5\">\n <summary className=\"text-[11px] text-muted-foreground/70 cursor-pointer hover:text-foreground\">\n Context\n </summary>\n <pre className=\"mt-1 text-[11px] bg-header-bg p-1.5 rounded-sm overflow-x-auto text-muted-foreground\">\n {JSON.stringify(warning.context, null, 2)}\n </pre>\n </details>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport { AlertTriangle } from 'lucide-react';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport { FORMAT } from '../../lib/env';\n\n// Theme names registered in the server-side core packages. Documents may\n// reference these even without a matching customThemes entry.\nconst BUILTIN_THEMES: Record<string, readonly string[]> = {\n pptx: ['default', 'dark', 'minimal'],\n docx: ['minimal', 'corporate', 'modern'],\n};\n\nexport function UnavailableThemeWarning({ className }: { className?: string }) {\n const activeTab = useDocumentsStore((s) => s.activeTab);\n const documentTypes = useDocumentsStore((s) => s.documentTypes);\n const documents = useDocumentsStore((s) => s.documents);\n const customThemes = useThemesStore((s) => s.customThemes);\n\n const missingThemeName = useMemo(() => {\n if (!activeTab) return null;\n if (documentTypes[activeTab] === 'application/json+theme') return null;\n\n const doc = documents.find((d) => d.name === activeTab);\n if (!doc?.text) return null;\n\n let themeName: unknown;\n try {\n themeName = JSON.parse(doc.text)?.props?.theme;\n } catch {\n return null;\n }\n if (typeof themeName !== 'string' || !themeName) return null;\n\n if (BUILTIN_THEMES[FORMAT]?.includes(themeName)) return null;\n\n for (const ct of Object.values(customThemes)) {\n if (ct.valid && ct.name === themeName) return null;\n }\n\n return themeName;\n }, [activeTab, documentTypes, documents, customThemes]);\n\n if (!missingThemeName) return null;\n\n return (\n <div\n className={`flex items-start gap-2 rounded-sm border border-transparent bg-warning/10 px-3 py-2 ${className ?? ''}`}\n >\n <AlertTriangle className=\"h-3.5 w-3.5 mt-0.5 text-warning flex-shrink-0\" />\n <div className=\"flex-1 min-w-0 text-xs leading-relaxed\">\n <span className=\"font-medium text-warning\">\n Theme{' '}\n <code className=\"bg-warning/20 px-1 py-0.5 rounded-sm text-warning\">\n {missingThemeName}\n </code>{' '}\n is not available.\n </span>{' '}\n <span className=\"text-warning/80\">\n Add it as a custom theme or use a built-in theme (\n {BUILTIN_THEMES[FORMAT]?.join(', ')}). The renderer will fall back to\n a default.\n </span>\n </div>\n </div>\n );\n}\n","/**\n * Build the `@font-face` block for the fast in-browser DOCX preview.\n *\n * The generated .docx never carries font bytes (`word/fonts/` is always\n * empty — see core-docx's no-font-embedding regression suite), so\n * docx-preview's own `renderFontTable` contributes nothing and the preview\n * silently renders in whatever the host machine happens to have. We\n * synthesize the faces instead, from the document's `fontRegistry` plus the\n * bundled Google catalog.\n *\n * The load-bearing subtlety is weight. core-docx rewrites runs through\n * `synthesizeFamilyName`, so `{ family: 'Inter', fontWeight: 300 }` reaches\n * the preview as the family literal `\"Inter Light\"` with no bold toggle,\n * while docx-preview only ever emits `font-weight: bold | normal`. A face\n * registered as `Inter` at weight 300 would therefore never be selected —\n * every non-RIBBI weight needs a second rule under its synthetic sub-family\n * name at plain 400/normal. Google's own stylesheet declares only\n * `font-family: 'Inter'`, which is why the Google path fetches and rewrites\n * the CSS rather than just linking it.\n *\n * Kept free of DOM access so it is unit-testable — packages/jto runs vitest\n * with the default `node` environment. render.ts owns the DOM glue.\n */\n\nimport {\n WEIGHT_LABELS,\n POPULAR_GOOGLE_FONTS,\n isSafeFont,\n isAllowedFontUrl,\n collectFontNamesFromDocx,\n type FontRegistryEntry,\n} from '@json-to-office/shared';\n\n/** One resolved face, before expansion to synthetic sub-family names. */\nexport interface PreviewFontFace {\n family: string;\n weight: number;\n italic: boolean;\n /**\n * Raw resource for a document-declared source: a `data:` URI or an\n * allowlisted https URL. Kept unwrapped so the CSS writer owns quoting —\n * see renderFontFaceCss.\n */\n url?: string;\n /**\n * Pre-built CSS `src` value. Only ever set from Google's own stylesheet,\n * which we fetch ourselves and validate; never from document input.\n */\n src?: string;\n unicodeRange?: string;\n /** Backed by a variable font, so synthetic names must pin the wght axis. */\n variable?: boolean;\n}\n\nexport interface PreviewFontAssets {\n css: string;\n /** Fallback `<link rel=stylesheet>` hrefs when CSS rewriting failed. */\n googleHrefs: string[];\n}\n\n/** Cap on generated CSS — it ends up inside an HTML `srcdoc` attribute. */\nconst DEFAULT_MAX_BYTES = 8 * 1024 * 1024;\n\nfunction asArray(v: unknown): FontRegistryEntry[] {\n return Array.isArray(v) ? (v as FontRegistryEntry[]) : [];\n}\n\n/**\n * Collect registry entries from the document and any custom themes.\n * Document entries win, mirroring the server's precedence where\n * caller-supplied entries beat theme-declared ones.\n */\nexport function extractFontRegistries(\n jsonText: string | undefined,\n customThemes: Record<string, unknown> | undefined\n): FontRegistryEntry[] {\n let docEntries: FontRegistryEntry[] = [];\n if (typeof jsonText === 'string' && jsonText.length > 0) {\n try {\n const parsed = JSON.parse(jsonText) as {\n props?: { fontRegistry?: unknown };\n };\n docEntries = asArray(parsed?.props?.fontRegistry);\n } catch {\n // A mid-edit document is not valid JSON. The preview gets no registry\n // fonts rather than failing to render.\n return [];\n }\n }\n\n const themeEntries: FontRegistryEntry[] = [];\n for (const theme of Object.values(customThemes ?? {})) {\n themeEntries.push(\n ...asArray((theme as { fontRegistry?: unknown })?.fontRegistry)\n );\n }\n\n const byFamily = new Map<string, FontRegistryEntry>();\n for (const e of [...themeEntries, ...docEntries]) {\n if (e && typeof e.family === 'string') {\n byFamily.set(e.family.toLowerCase(), e);\n }\n }\n return [...byFamily.values()];\n}\n\n/**\n * The family names a run may actually carry for a given weight, mirroring\n * `synthesizeFamilyName`.\n *\n * Weight 400/700 keep the canonical name and rely on docx-preview's\n * bold/normal toggle. Other canonical weights arrive as a synthetic\n * sub-family carrying no toggle, so their rule must be plain 400/normal.\n */\nexport function synthesizedFamilyNames(\n family: string,\n weight: number,\n italic: boolean\n): { family: string; cssWeight: number; cssStyle: 'normal' | 'italic' }[] {\n const out = [\n {\n family,\n cssWeight: weight,\n cssStyle: (italic ? 'italic' : 'normal') as 'normal' | 'italic',\n },\n ];\n const label = WEIGHT_LABELS[weight];\n if (weight !== 400 && weight !== 700 && label) {\n out.push({\n family: `${family} ${label}${italic ? ' Italic' : ''}`,\n cssWeight: 400,\n cssStyle: 'normal',\n });\n }\n return out;\n}\n\n/**\n * A `kind:\"data\"` payload is either bare base64 or a base64 data: URI, and\n * nothing else. Anything outside that alphabet is a crafted payload trying to\n * break out of the `url(\"…\")` it would be interpolated into — most usefully\n * `\"),url(\"https://attacker/x` to append a source the host allowlist would\n * have rejected. Reject rather than escape: there is no legitimate font here.\n */\nconst DATA_FONT_RE =\n /^(?:data:[a-z0-9.+-]+\\/[a-z0-9.+-]+;base64,)?[A-Za-z0-9+/=\\s]+$/i;\n\nfunction dataUrlFor(raw: string): string | null {\n if (!DATA_FONT_RE.test(raw)) return null;\n return raw.startsWith('data:') ? raw : `data:font/ttf;base64,${raw}`;\n}\n\n/** Turn one registry entry into concrete faces. */\nexport function facesFromRegistryEntry(\n entry: FontRegistryEntry\n): PreviewFontFace[] {\n const faces: PreviewFontFace[] = [];\n\n for (const source of entry.sources ?? []) {\n // `safe` needs nothing; `file` paths only exist server-side; `google`\n // goes through the fetch-and-rewrite path instead.\n if (\n source.kind === 'safe' ||\n source.kind === 'file' ||\n source.kind === 'google'\n ) {\n continue;\n }\n\n const italic = 'italic' in source ? Boolean(source.italic) : false;\n const weight = 'weight' in source && source.weight ? source.weight : 400;\n\n if (source.kind === 'data') {\n // No format() hint: it is advisory, browsers sniff, and the real\n // detector is Buffer-based and unavailable in the browser.\n const url = dataUrlFor(source.data);\n if (!url) continue;\n faces.push({ family: entry.family, weight, italic, url });\n continue;\n }\n\n // `url` and `variable` both point at a remote file; apply the same host\n // policy the Node fetchers use so a crafted document cannot make the\n // preview reach arbitrary hosts.\n if (!isAllowedFontUrl(source.url)) continue;\n faces.push({\n family: entry.family,\n weight,\n italic,\n url: source.url,\n variable: source.kind === 'variable',\n });\n }\n return faces;\n}\n\n/** Google catalog families referenced by the document. */\nexport function googleFamiliesFor(\n referencedNames: Set<string>,\n registryEntries: FontRegistryEntry[],\n referencedWeights: Set<number>\n): { family: string; weights: number[]; italics: boolean }[] {\n // Registry bytes win over the Google stylesheet — but only for the weights\n // they actually supply. Treating the whole family as covered would mean\n // that embedding a font (the Custom tab registers 400/700, an upload\n // registers one weight) silently drops every other weight the document\n // uses, so a `fontWeight: 500` run would lose the face it just gained.\n //\n // Coverage is read off the faces `facesFromRegistryEntry` really returns,\n // never off the sources directly. It drops more than the obvious\n // google/safe pair — `file` paths exist only server-side, a data payload\n // outside the base64 grammar is rejected, and a url outside the host\n // allowlist is dropped — and a source that produces no face must not\n // suppress the Google fallback, or the preview loses the family entirely.\n // Deriving from the faces keeps the two rules from drifting apart.\n const coveredWeights = new Map<string, Set<number>>();\n for (const e of registryEntries) {\n for (const face of facesFromRegistryEntry(e)) {\n const key = face.family.toLowerCase();\n let set = coveredWeights.get(key);\n if (!set) coveredWeights.set(key, (set = new Set<number>()));\n set.add(face.weight);\n }\n }\n\n const out: { family: string; weights: number[]; italics: boolean }[] = [];\n const emitted = new Set<string>();\n\n for (const name of referencedNames) {\n if (isSafeFont(name)) continue;\n const lower = name.toLowerCase();\n if (emitted.has(lower)) continue;\n const match = POPULAR_GOOGLE_FONTS.find(\n (f) => f.family.toLowerCase() === lower\n );\n if (!match) continue;\n emitted.add(lower);\n\n const already = coveredWeights.get(lower);\n const wanted = new Set<number>([400, 700, ...referencedWeights]);\n const weights = match.weights.filter(\n (w) => wanted.has(w) && !already?.has(w)\n );\n // Every weight this document uses already has real bytes.\n if (weights.length === 0) continue;\n out.push({ family: match.family, weights, italics: match.hasItalic });\n }\n return out;\n}\n\n/**\n * Google's css2 endpoint rejects unsorted axis tuples with a 400, so weights\n * ascend and `ital` tuples are grouped roman-then-italic.\n */\nexport function buildGoogleCss2Href(\n family: string,\n weights: number[],\n italics: boolean\n): string {\n const sorted = [...new Set(weights)].sort((a, b) => a - b);\n const axis = italics\n ? `ital,wght@${[\n ...sorted.map((w) => `0,${w}`),\n ...sorted.map((w) => `1,${w}`),\n ].join(';')}`\n : `wght@${sorted.join(';')}`;\n return `https://fonts.googleapis.com/css2?family=${encodeURIComponent(\n family\n )}:${axis}&display=swap`;\n}\n\n/** Parsed Google CSS, memoized per (family, weights, italics). */\nconst googleFaceCache = new Map<string, Promise<PreviewFontFace[]>>();\n\n/**\n * How long the Google stylesheet fetch may take before we give up on\n * rewriting it and fall back to a plain `<link>`.\n *\n * Nothing downstream bounds this: render.ts awaits `buildPreviewFontAssets`\n * *after* its 10s renderAsync race has already settled, and no caller of\n * `renderDocument` races it either — so a stalled request would leave the\n * preview promise unsettled and the pane spinning forever. Short on purpose:\n * the fallback path still covers 400/700, so waiting longer buys only the\n * intermediate weights.\n */\nexport const GOOGLE_CSS_TIMEOUT_MS = 3000;\n\n/**\n * Fetch a Google stylesheet and re-express it as faces we own.\n *\n * A plain `<link>` would only ever declare `font-family: 'Inter'`, so runs\n * carrying the synthetic `\"Inter Light\"` name would not match. Parsing the\n * CSS gives us the real gstatic URLs, which `renderFontFaceCss` then re-emits\n * under both the canonical and synthetic names.\n *\n * Rejects on timeout rather than resolving empty, so the caller's existing\n * catch degrades to the stylesheet link instead of emitting no face at all.\n */\nexport async function fetchGoogleFacesRewritten(\n family: string,\n weights: number[],\n italics: boolean,\n fetchImpl: typeof fetch = fetch,\n timeoutMs: number = GOOGLE_CSS_TIMEOUT_MS\n): Promise<PreviewFontFace[]> {\n const href = buildGoogleCss2Href(family, weights, italics);\n const cached = googleFaceCache.get(href);\n if (cached) return cached;\n\n const pending = (async () => {\n // The abort cancels a real in-flight request; the race is what\n // guarantees rejection, since an injected or non-conforming fetch may\n // ignore the signal entirely. Both halves of the exchange are raced —\n // a stalled body read hangs exactly like a stalled response.\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const expiry = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n reject(new Error(`Google Fonts CSS timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n try {\n const res = await Promise.race([\n fetchImpl(href, { signal: controller.signal }),\n expiry,\n ]);\n if (!res.ok) throw new Error(`Google Fonts CSS ${res.status}`);\n const text = await Promise.race([res.text(), expiry]);\n return parseGoogleCss(text, family);\n } finally {\n // Also stops `expiry` from ever rejecting once we are done with it.\n if (timer) clearTimeout(timer);\n }\n })();\n\n googleFaceCache.set(href, pending);\n // A failed fetch must not poison the cache for the rest of the session.\n pending.catch(() => googleFaceCache.delete(href));\n return pending;\n}\n\n/** Split a Google css2 response into faces. Exported for testing. */\nexport function parseGoogleCss(css: string, family: string): PreviewFontFace[] {\n const faces: PreviewFontFace[] = [];\n for (const block of css.split('@font-face')) {\n const src = /src:\\s*([^;]+);/.exec(block)?.[1]?.trim();\n if (!src) continue;\n const style = /font-style:\\s*(\\w+)/.exec(block)?.[1] ?? 'normal';\n const weight = Number(/font-weight:\\s*(\\d+)/.exec(block)?.[1] ?? '400');\n const rawRange = /unicode-range:\\s*([^;]+);/.exec(block)?.[1]?.trim();\n // Interpolated unquoted, so hold it to the grammar rather than trusting\n // the response body.\n const unicodeRange =\n rawRange && /^[Uu]\\+[0-9A-Fa-f?,+\\-Uu\\s]*$/.test(rawRange)\n ? rawRange\n : undefined;\n faces.push({\n family,\n weight: Number.isFinite(weight) ? weight : 400,\n italic: style === 'italic',\n src,\n ...(unicodeRange ? { unicodeRange } : {}),\n });\n }\n return faces;\n}\n\n/**\n * Escape for a CSS string that will be serialized into a `<style>` element.\n *\n * `<style>` is HTML raw text: its content is emitted verbatim, so a literal\n * `</style>` anywhere inside — including in the middle of a quoted CSS\n * string — closes the element and turns everything after it into markup. Font\n * family names come straight from document JSON, so escaping `\\` and `\"` is\n * not enough. `\\3c ` is the CSS escape for `<` and resolves back to the same\n * character, so the family still matches while `</style>` can never appear.\n */\nfunction escapeCssString(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/</g, '\\\\3c ');\n}\n\n/**\n * Expand faces through `synthesizedFamilyNames` and render the stylesheet.\n * De-dupes identical rules, which matters because a variable source and a\n * Google fallback can legitimately produce the same face twice.\n */\nexport function renderFontFaceCss(\n faces: PreviewFontFace[],\n maxBytes: number = DEFAULT_MAX_BYTES\n): string {\n const seen = new Set<string>();\n const rules: string[] = [];\n let bytes = 0;\n let dropped = 0;\n\n for (const face of faces) {\n // A document-declared source is quoted here, by the writer that knows the\n // output context; a Google-derived `src` is used as-is but must not carry\n // a `<`, which its own stylesheet never contains.\n const src = face.url\n ? `url(\"${escapeCssString(face.url)}\")`\n : face.src && !face.src.includes('<')\n ? face.src\n : undefined;\n if (!src) continue;\n\n for (const n of synthesizedFamilyNames(\n face.family,\n face.weight,\n face.italic\n )) {\n const key = `${n.family}|${n.cssWeight}|${n.cssStyle}|${src}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n // A synthetic name carries no weight of its own, so a variable font\n // would render at its default instance without an explicit axis pin.\n const isSynthetic = n.family !== face.family;\n const variation =\n face.variable && isSynthetic\n ? `font-variation-settings:\"wght\" ${face.weight};`\n : '';\n\n const rule =\n `@font-face{font-family:\"${escapeCssString(n.family)}\";` +\n `src:${src};` +\n `font-weight:${n.cssWeight};` +\n `font-style:${n.cssStyle};` +\n `font-display:swap;` +\n variation +\n (face.unicodeRange ? `unicode-range:${face.unicodeRange};` : '') +\n `}`;\n\n if (bytes + rule.length > maxBytes) {\n dropped++;\n continue;\n }\n bytes += rule.length;\n rules.push(rule);\n }\n }\n\n if (dropped > 0) {\n console.warn(\n `Preview fonts: dropped ${dropped} @font-face rule(s) over the ${maxBytes}-byte budget.`\n );\n }\n return rules.join('\\n');\n}\n\n/** Collect numeric `fontWeight` values, mirroring the server's walker. */\nexport function collectReferencedWeights(node: unknown): Set<number> {\n const out = new Set<number>();\n const visit = (n: unknown): void => {\n if (!n || typeof n !== 'object') return;\n if (Array.isArray(n)) {\n for (const item of n) visit(item);\n return;\n }\n for (const [k, v] of Object.entries(n as Record<string, unknown>)) {\n if (k === 'fontWeight' && typeof v === 'number') out.add(v);\n else visit(v);\n }\n };\n visit(node);\n return out;\n}\n\n/**\n * Everything the preview head needs. Registry fonts become inline\n * `@font-face` rules; Google catalog families are fetched and rewritten so\n * synthetic sub-family names resolve, falling back to a plain stylesheet\n * link (which still covers 400/700) if that fetch fails.\n */\nexport async function buildPreviewFontAssets(\n jsonText: string | undefined,\n customThemes: Record<string, unknown> | undefined,\n opts?: {\n fetchImpl?: typeof fetch;\n maxBytes?: number;\n /** Per-family cap on the Google CSS fetch. Injectable for tests. */\n googleTimeoutMs?: number;\n }\n): Promise<PreviewFontAssets> {\n const entries = extractFontRegistries(jsonText, customThemes);\n\n let parsedDoc: unknown;\n if (typeof jsonText === 'string' && jsonText.length > 0) {\n try {\n parsedDoc = JSON.parse(jsonText);\n } catch {\n parsedDoc = undefined;\n }\n }\n\n // Union the document and every custom theme, the same way the server's\n // collectReferencedNames does.\n const names = new Set<string>();\n const weights = new Set<number>();\n if (parsedDoc !== undefined) {\n for (const n of collectFontNamesFromDocx(parsedDoc)) names.add(n);\n for (const w of collectReferencedWeights(parsedDoc)) weights.add(w);\n }\n for (const theme of Object.values(customThemes ?? {})) {\n for (const n of collectFontNamesFromDocx(theme)) names.add(n);\n for (const w of collectReferencedWeights(theme)) weights.add(w);\n }\n\n const faces: PreviewFontFace[] = [];\n for (const entry of entries) faces.push(...facesFromRegistryEntry(entry));\n\n const googleHrefs: string[] = [];\n for (const g of googleFamiliesFor(names, entries, weights)) {\n try {\n faces.push(\n ...(await fetchGoogleFacesRewritten(\n g.family,\n g.weights,\n g.italics,\n opts?.fetchImpl ?? fetch,\n opts?.googleTimeoutMs\n ))\n );\n } catch {\n // Degrade to a plain link: 400/700 still render, intermediate weights\n // fall back to the host.\n googleHrefs.push(buildGoogleCss2Href(g.family, g.weights, g.italics));\n }\n }\n\n return { css: renderFontFaceCss(faces, opts?.maxBytes), googleHrefs };\n}\n","import { FORMAT } from './env';\nimport { API_ENDPOINTS } from '../config/api';\nimport { env } from './env';\nimport { buildPreviewFontAssets } from './preview-fonts';\n\nexport type RenderPayload = {\n iframeSrc?: string;\n iframeSrcDoc?: string;\n cleanup?: () => void;\n};\n\nasync function renderDocxWithDocxJS(\n blob: Blob,\n jsonText?: string,\n customThemes?: Record<string, unknown>\n): Promise<RenderPayload> {\n const docx_preview = await import('docx-preview');\n\n const bodyEl = document.createElement('body');\n const headEl = document.createElement('head');\n\n const renderPromise = docx_preview.renderAsync(blob, bodyEl, headEl, {\n inWrapper: true,\n });\n\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => {\n reject(new Error('DocxJS renderAsync timed out after 10 seconds'));\n }, 10000);\n });\n\n await Promise.race([renderPromise, timeoutPromise]);\n\n // The DOCX never carries font bytes (word/fonts/ is always empty), so\n // docx-preview's own renderFontTable contributes nothing. Synthesize the\n // @font-face block from the document's fontRegistry + Google catalog.\n // headEl is detached, so nothing is fetched by the parent page — only the\n // iframe loads these once the serialized HTML is handed to srcdoc.\n try {\n const { css, googleHrefs } = await buildPreviewFontAssets(\n jsonText,\n customThemes\n );\n for (const href of googleHrefs) {\n const gf = document.createElement('link');\n gf.rel = 'stylesheet';\n gf.href = href;\n headEl.appendChild(gf);\n }\n if (css) {\n const fontStyleEl = document.createElement('style');\n fontStyleEl.textContent = css;\n headEl.appendChild(fontStyleEl);\n }\n } catch (err) {\n console.warn('Preview font injection failed; using host fonts', err);\n }\n\n const overrideStyleEl = document.createElement('link');\n overrideStyleEl.rel = 'stylesheet';\n overrideStyleEl.href = `${env.basePath}/css/preview/docxjs.css`;\n headEl.appendChild(overrideStyleEl);\n\n const htmlEl = document.createElement('html');\n htmlEl.appendChild(headEl);\n htmlEl.appendChild(bodyEl);\n\n return { iframeSrcDoc: htmlEl.outerHTML };\n}\n\nasync function renderWithLibreOffice(\n name: string,\n blob: Blob,\n jsonText?: string,\n customThemes?: Record<string, unknown>\n): Promise<RenderPayload> {\n // When we know the source JSON, hit the from-json endpoint. The server\n // generates + converts in one step and passes resolved fonts directly to\n // the LibreOffice font stager — embedded fonts render correctly in the PDF.\n // Falling back to the upload path is still useful if the JSON is lost or\n // we're previewing an externally-supplied file.\n const useJsonPath = typeof jsonText === 'string' && jsonText.length > 0;\n\n let response: Response;\n if (useJsonPath) {\n let jsonDefinition: unknown;\n try {\n jsonDefinition = JSON.parse(jsonText!);\n } catch (err) {\n throw new Error(`Invalid JSON document: ${(err as Error).message}`);\n }\n const body: Record<string, unknown> = {\n jsonDefinition,\n customThemes: customThemes ?? {},\n // sourceName lets the server resolve relative asset paths against the\n // discovered document's own directory (#142). Names only — the server\n // maps them to paths itself.\n options: { sourceName: name },\n };\n response = await fetch(API_ENDPOINTS.preview.libreofficeFromJson, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n } else {\n const formData = new FormData();\n const ext = FORMAT === 'pptx' ? '.pptx' : '.docx';\n formData.append('file', blob, `${name}${ext}`);\n response = await fetch(API_ENDPOINTS.preview.libreoffice, {\n method: 'POST',\n body: formData,\n });\n }\n\n if (!response.ok) {\n let message = `LibreOffice preview failed (${response.status})`;\n try {\n const json = await response.json();\n if (json && typeof json === 'object' && typeof json.error === 'string') {\n message = json.error;\n }\n } catch {}\n throw new Error(message);\n }\n\n const pdfBlob = await response.blob();\n if (!pdfBlob.size) {\n throw new Error('LibreOffice preview returned an empty PDF');\n }\n\n const objectUrl = URL.createObjectURL(pdfBlob);\n return {\n iframeSrc: objectUrl,\n cleanup: () => URL.revokeObjectURL(objectUrl),\n };\n}\n\nexport function cleanupIframe(iframe: HTMLIFrameElement) {\n try {\n if (iframe.contentWindow) {\n iframe.contentWindow.location.replace('about:blank');\n }\n iframe.src = 'about:blank';\n iframe.srcdoc = '';\n if (iframe.parentNode) {\n iframe.parentNode.removeChild(iframe);\n }\n } catch (error) {\n console.warn('Error cleaning up iframe:', error);\n }\n}\n\nexport type RenderLibrary = 'docxjs' | 'LibreOffice';\n\nexport async function renderDocument(\n name: string,\n blob: Blob,\n library: RenderLibrary = FORMAT === 'docx' ? 'docxjs' : 'LibreOffice',\n _baseUrl?: string,\n jsonText?: string,\n customThemes?: Record<string, unknown>\n) {\n try {\n if (!blob || blob.size === 0) {\n throw new Error('Invalid or empty document blob');\n }\n\n let payload: RenderPayload;\n\n if (FORMAT === 'docx' && library === 'docxjs') {\n payload = await renderDocxWithDocxJS(blob, jsonText, customThemes);\n } else {\n payload = await renderWithLibreOffice(name, blob, jsonText, customThemes);\n }\n\n return { status: 'success' as const, name, payload };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { status: 'error' as const, name, payload: new Error(errorMessage) };\n }\n}\n\n// Keep backward compat exports for pptx code\nexport const renderPptx = (name: string, blob: Blob, baseUrl: string) =>\n renderDocument(name, blob, 'LibreOffice', baseUrl);\n","import * as React from 'react';\nimport * as ProgressPrimitive from '@radix-ui/react-progress';\nimport { cn } from '../../lib/utils';\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-4 w-full overflow-hidden rounded-full bg-secondary',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n));\nProgress.displayName = ProgressPrimitive.Root.displayName;\n\nexport { Progress };\n","import { useEffect, useState } from 'react';\nimport { Badge } from './ui/badge';\nimport { Progress } from './ui/progress';\nimport { API_ENDPOINTS } from '../config/api';\nimport { FORMAT } from '../lib/env';\n\ninterface CacheStats {\n document: {\n hits: number;\n misses: number;\n hitRate: number;\n size: number;\n itemCount: number;\n enabled: boolean;\n };\n components?: ComponentCacheData;\n rasterizer?: RasterizerCacheData;\n}\n\ninterface ComponentStatistics {\n type: string;\n hits: number;\n misses: number;\n avgProcessTime: number;\n avgSize: number;\n entries: number;\n hitRate?: number;\n totalRequests?: number;\n memoryUsage?: number;\n}\n\ninterface BypassedComponentStatistics {\n type: string;\n renders: number;\n reason: string;\n}\n\ninterface ComponentCacheData {\n entries: number;\n totalSize: number;\n hitRate: number;\n totalHits: number;\n totalMisses: number;\n avgResponseTime: number;\n evictions: number;\n componentStats: ComponentStatistics[];\n bypassedComponents?: BypassedComponentStatistics[];\n}\n\ninterface RasterizerCacheData {\n diskHits: number;\n diskMisses: number;\n hitRate: number;\n dedupedRequests: number;\n rendered: number;\n failed: number;\n entries: number;\n bytes: number;\n prepass?: {\n documents: number;\n collected: number;\n unique: number;\n };\n}\n\nconst BYPASS_REASON_LABELS: Record<string, string> = {\n 'dynamic-context': 'depends on render-time context',\n 'bookmark-id': 'carries a bookmark id',\n 'revision-ids': 'carries revision ids',\n};\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n\nexport function CacheMetrics() {\n const [stats, setStats] = useState<CacheStats | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n\n const fetchData = async () => {\n try {\n const response = await fetch(API_ENDPOINTS.cacheStats, {\n signal: controller.signal,\n });\n if (!response.ok) throw new Error('Failed to fetch cache stats');\n const data = await response.json();\n\n if (!controller.signal.aborted) {\n setStats(data.data);\n setError(null);\n }\n } catch (err) {\n if (!controller.signal.aborted) {\n if (err instanceof Error && err.name !== 'AbortError') {\n setError(err.message);\n } else if (!(err instanceof Error) || err.name !== 'AbortError') {\n setError('Failed to load cache stats');\n }\n }\n } finally {\n if (!controller.signal.aborted) setLoading(false);\n }\n };\n\n fetchData();\n const interval = setInterval(fetchData, 5000);\n\n const handleCacheCleared = () => fetchData();\n window.addEventListener('cache:cleared', handleCacheCleared);\n\n return () => {\n controller.abort();\n clearInterval(interval);\n window.removeEventListener('cache:cleared', handleCacheCleared);\n };\n }, []);\n\n if (loading) {\n return (\n <div className=\"flex items-center justify-center p-8\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-primary\" />\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"text-destructive p-4\">\n Error loading cache metrics: {error}\n </div>\n );\n }\n\n if (!stats) return null;\n\n const { document: doc } = stats;\n const hitRatePct = doc.hitRate * 100;\n\n return (\n <div className=\"space-y-4\">\n {/* Summary row */}\n <div className=\"flex items-center gap-6 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">Hit Rate</span>{' '}\n <span className=\"font-semibold text-base\">\n {hitRatePct.toFixed(1)}%\n </span>\n <span className=\"text-muted-foreground ml-1\">\n ({doc.hits} hits / {doc.misses} misses)\n </span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">Size</span>{' '}\n <span className=\"font-semibold\">{formatBytes(doc.size)}</span>\n <span className=\"text-muted-foreground ml-1\">\n ({doc.itemCount} items)\n </span>\n </div>\n <Badge variant={doc.enabled ? 'default' : 'secondary'}>\n {doc.enabled ? 'Enabled' : 'Disabled'}\n </Badge>\n </div>\n\n <Progress\n value={hitRatePct}\n className=\"h-2\"\n aria-label=\"Cache hit rate\"\n />\n\n {/* Module-level breakdown (docx only) */}\n {FORMAT === 'docx' && stats.components && (\n <ComponentBreakdown data={stats.components} />\n )}\n\n {/* Visual rasterizer caches (disk PNG cache + batch dedupe) */}\n {stats.rasterizer && <RasterizerBreakdown data={stats.rasterizer} />}\n </div>\n );\n}\n\nfunction ComponentBreakdown({ data }: { data: ComponentCacheData }) {\n const bypassed = data.bypassedComponents ?? [];\n if (data.componentStats.length === 0 && bypassed.length === 0) return null;\n\n return (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium\">Module Breakdown</h4>\n <div className=\"space-y-1\">\n {data.componentStats.map((stat) => {\n const hitRate = (stat.hitRate || 0) * 100;\n const requests = stat.totalRequests || stat.hits + stat.misses;\n const memory = stat.memoryUsage || stat.entries * stat.avgSize || 0;\n\n return (\n <div key={stat.type} className=\"px-3 py-1.5 text-sm\">\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"font-medium\">{stat.type}</span>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{hitRate.toFixed(0)}% hit</span>\n <span>{requests} req</span>\n <span>{formatBytes(memory)}</span>\n </div>\n </div>\n <Progress value={hitRate} className=\"h-1.5\" />\n </div>\n );\n })}\n {/* Types that skip the cache on purpose — rendered so the breakdown\n covers every component the document used, not only cacheable\n ones. No hit-rate bar: there is nothing to hit. */}\n {bypassed.map((stat) => (\n <div key={`bypass-${stat.type}`} className=\"px-3 py-1.5 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium text-muted-foreground\">\n {stat.type}\n </span>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>\n uncached by design\n {BYPASS_REASON_LABELS[stat.reason]\n ? ` — ${BYPASS_REASON_LABELS[stat.reason]}`\n : ''}\n </span>\n <span>{stat.renders} renders</span>\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction RasterizerBreakdown({ data }: { data: RasterizerCacheData }) {\n const lookups = data.diskHits + data.diskMisses;\n const activity =\n lookups + data.dedupedRequests + data.rendered + data.entries;\n if (activity === 0) return null;\n\n const hitRatePct = data.hitRate * 100;\n const dedupeSaved = data.prepass\n ? data.prepass.collected - data.prepass.unique\n : data.dedupedRequests;\n\n return (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium\">Visual Rasterizer</h4>\n <div className=\"px-3 py-1.5 text-sm space-y-1.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-muted-foreground\">Disk cache</span>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>\n {lookups > 0 ? `${hitRatePct.toFixed(0)}% hit` : 'no lookups'}\n </span>\n <span>\n ({data.diskHits} hits / {data.diskMisses} misses)\n </span>\n <span>\n {data.entries} PNGs, {formatBytes(data.bytes)}\n </span>\n </div>\n </div>\n <Progress\n value={hitRatePct}\n className=\"h-1.5\"\n aria-label=\"Rasterizer disk cache hit rate\"\n />\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {data.rendered} rendered\n {data.failed > 0 ? `, ${data.failed} failed` : ''}\n </span>\n <span>\n {dedupeSaved} duplicate visual{dedupeSaved === 1 ? '' : 's'} deduped\n {data.prepass\n ? ` (${data.prepass.collected} collected → ${data.prepass.unique} unique)`\n : ''}\n </span>\n </div>\n </div>\n </div>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n memo,\n} from 'react';\nimport { InfoIcon } from 'lucide-react';\nimport { PreviewFrameMemoized } from './preview-frame';\nimport { PreviewHeaderMemoized } from './preview-header';\nimport { WarningsPanel } from './warnings-panel';\nimport { UnavailableThemeWarning } from './unavailable-theme-warning';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { Separator } from '../ui/separator';\nimport { useOutputStore } from '../../store/output-store-provider';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { renderDocument } from '../../lib/render';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport { CacheMetrics } from '../cache-metrics';\nimport { FORMAT, FORMAT_LABEL } from '../../lib/env';\n\n/**\n * Tiny live countdown that ticks every 100ms and shows the\n * remaining debounce time before generation starts.\n * Renders nothing once the deadline is reached.\n */\nconst DebounceCountdown = memo(function DebounceCountdown({\n editTimestamp,\n debounceMs,\n}: {\n editTimestamp: number;\n debounceMs: number;\n}) {\n const [remaining, setRemaining] = useState(() =>\n Math.max(0, editTimestamp + debounceMs - Date.now())\n );\n\n useEffect(() => {\n let id: ReturnType<typeof setInterval> | undefined;\n const tick = () => {\n const r = Math.max(0, editTimestamp + debounceMs - Date.now());\n setRemaining(r);\n if (r <= 0 && id != null) clearInterval(id);\n };\n tick();\n id = setInterval(tick, 100);\n return () => {\n if (id != null) clearInterval(id);\n };\n }, [editTimestamp, debounceMs]);\n\n if (remaining <= 0) return null;\n\n const secs = (remaining / 1000).toFixed(1);\n const pct = Math.min(100, (remaining / debounceMs) * 100);\n\n return (\n <span className=\"inline-flex items-center gap-1.5 text-xs text-warning tabular-nums\">\n <span\n className=\"h-1 rounded-full bg-warning/60 transition-[width] duration-100\"\n style={{ width: `${Math.round(pct * 0.4)}px` }}\n />\n {secs}s\n </span>\n );\n});\n\nexport function Preview() {\n const {\n autoReload,\n renderingLibrary,\n saveDocumentDebounceWait,\n setSettings,\n } = useSettingsStore((state) => state);\n const {\n name,\n text,\n blob,\n isGenerating,\n generationProgress,\n generationStartedAt,\n cancelGeneration,\n globalError,\n cacheStatus,\n cacheHitRate,\n warnings,\n isRendering,\n isPreviewStale,\n editSequence,\n lastBuiltSequence,\n editTimestamp,\n hasValidationErrors,\n setOutput,\n } = useOutputStore((state) => state);\n const activeTab = useDocumentsStore((state) => state.activeTab);\n const documentTypes = useDocumentsStore((state) => state.documentTypes);\n // Editor text for \"Copy standard components\" — exists before the first Run,\n // unlike the output store's `text` (#155). Themes have no expansion.\n const editorDocumentText = useDocumentsStore((s) =>\n s.activeTab && s.documentTypes[s.activeTab] !== 'application/json+theme'\n ? s.documents.find((d) => d.name === s.activeTab)?.text\n : undefined\n );\n // Select the raw map (stable reference until themes mutate), then memoize\n // the transform. A selector that returns a freshly-constructed object on\n // every call would burn through Zustand's Object.is equality and retrigger\n // renders indefinitely.\n const customThemesMap = useThemesStore((state) => state.customThemes);\n const themesForServer = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const ct of Object.values(customThemesMap)) {\n if (ct.valid && ct.name && ct.parsed) out[ct.name] = ct.parsed;\n }\n return out;\n }, [customThemesMap]);\n\n const [iframeSrc, setIframeSrc] = useState<string | undefined>(undefined);\n const [iframeSrcDoc, setIframeSrcDoc] = useState<string | undefined>(\n undefined\n );\n const [showCacheMetrics, setShowCacheMetrics] = useState<boolean>(false);\n const iframeRef = React.useRef<HTMLIFrameElement>(null);\n\n const renderCleanupRef = useRef<(() => void) | null>(null);\n const pendingManualRenderRef = useRef(false);\n\n const cleanupRenderedPreview = useCallback(() => {\n if (renderCleanupRef.current) {\n renderCleanupRef.current();\n renderCleanupRef.current = null;\n }\n }, []);\n\n // Core render function\n const doRender = useCallback(\n async (\n docName: string,\n docBlob: Blob,\n docText?: string,\n themes?: Record<string, unknown>\n ) => {\n setOutput({\n isRendering: true,\n isPreviewStale: false,\n globalError: undefined,\n });\n\n try {\n const { status, payload } = await renderDocument(\n docName,\n docBlob,\n renderingLibrary,\n undefined,\n docText,\n themes\n );\n\n if (status !== 'success') {\n throw payload instanceof Error ? payload : new Error(String(payload));\n }\n\n cleanupRenderedPreview();\n setIframeSrc(payload.iframeSrc || undefined);\n setIframeSrcDoc(payload.iframeSrcDoc || undefined);\n renderCleanupRef.current = payload.cleanup || null;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n let displayMessage = errorMessage;\n if (errorMessage.includes('Failed to fetch')) {\n displayMessage =\n 'Network error: Unable to load required resources. Check if the server is running properly.';\n } else if (errorMessage.includes('timeout')) {\n displayMessage =\n 'Render timeout: The rendering process took too long.';\n }\n\n setOutput({ globalError: displayMessage });\n } finally {\n setOutput({ isRendering: false });\n }\n },\n [setOutput, cleanupRenderedPreview, renderingLibrary]\n );\n\n // Ref to always hold latest manual-render deps so the event listener never goes stale\n const manualRenderRef = useRef({ name, blob, text, doRender });\n useEffect(() => {\n manualRenderRef.current = { name, blob, text, doRender };\n });\n\n const handleManualRender = useCallback(async () => {\n // Set flag so blob-change effect renders the new blob when it arrives\n pendingManualRenderRef.current = true;\n // Flush debounces + trigger build via editor.tsx\n window.dispatchEvent(new CustomEvent('preview:flushAndBuild'));\n }, []); // stable — reads from ref\n\n // Auto-render when blob changes and docxjs + autoReload are active\n // Mark preview stale when blob changes but auto-render is OFF\n // Also render if a manual Run triggered the build (pendingManualRenderRef)\n useEffect(() => {\n if (blob && name && autoReload && renderingLibrary === 'docxjs') {\n doRender(name, blob, text, themesForServer);\n } else if (blob && name && pendingManualRenderRef.current) {\n pendingManualRenderRef.current = false;\n doRender(name, blob, text, themesForServer);\n } else if (blob && name) {\n setOutput({ isPreviewStale: true });\n }\n }, [\n blob,\n name,\n text,\n themesForServer,\n autoReload,\n renderingLibrary,\n doRender,\n setOutput,\n ]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRenderedPreview();\n };\n }, [cleanupRenderedPreview]);\n\n // Listen for global header events (stable — handleManualRender never changes)\n useEffect(() => {\n const onManual = () => handleManualRender();\n const onShowCache = () => setShowCacheMetrics(true);\n\n window.addEventListener('preview:manualRender', onManual);\n window.addEventListener('preview:showCacheMetrics', onShowCache);\n return () => {\n window.removeEventListener('preview:manualRender', onManual);\n window.removeEventListener('preview:showCacheMetrics', onShowCache);\n };\n }, [handleManualRender]);\n\n const localHeaderVisible =\n (useSettingsStore as any)?.getState?.().useGlobalPreviewHeader === false;\n\n return (\n <>\n <div className=\"flex h-full flex-col\">\n {localHeaderVisible && (\n <PreviewHeaderMemoized\n iframeRef={iframeRef}\n displayReloadButton={\n Boolean(iframeSrc) && !(iframeSrc?.startsWith('blob:') ?? false)\n }\n name={name?.trim() || 'Preview'}\n blob={blob}\n autoReload={autoReload}\n onToggleAutoReload={() => setSettings({ autoReload: !autoReload })}\n onManualRender={handleManualRender}\n isGenerating={isGenerating}\n isRendering={isRendering}\n onShowCacheMetrics={() => setShowCacheMetrics(true)}\n documentText={text}\n editorDocumentText={editorDocumentText}\n warnings={warnings}\n renderingLibrary={renderingLibrary}\n setRenderingLibrary={(lib) =>\n setSettings({ renderingLibrary: lib } as any)\n }\n />\n )}\n {/* The local header draws its own `border-b`; a standalone separator\n underneath it stacked two hairlines. */}\n {!localHeaderVisible && <Separator />}\n {FORMAT === 'docx' && renderingLibrary === 'docxjs' && (\n <div className=\"px-3 py-1.5 flex items-center gap-2 border-b bg-data-blue/10 text-xs text-data-blue\">\n <InfoIcon className=\"h-3.5 w-3.5 shrink-0\" />\n <span>\n The docxjs renderer is not 100% representative of the actual\n .docx. Use LibreOffice for higher fidelity.\n </span>\n </div>\n )}\n {/* Status Bar: cache + stale combined */}\n {(() => {\n const hasUnsyncedEdits =\n (editSequence ?? 0) > (lastBuiltSequence ?? 0);\n const isStale =\n (isPreviewStale || hasUnsyncedEdits) &&\n !isGenerating &&\n !isRendering;\n return (\n ((cacheStatus && cacheStatus !== 'UNKNOWN') || isStale) && (\n <div\n className={`px-3 py-1.5 flex items-center justify-between border-b overflow-hidden ${\n isStale ? 'bg-warning/10' : 'bg-header-bg'\n }`}\n >\n <div className=\"flex items-center gap-2 min-w-0 truncate\">\n {cacheStatus === 'HIT' && !isStale ? (\n <>\n <div className=\"h-1.5 w-1.5 rounded-full bg-success flex-shrink-0\" />\n <span className=\"text-xs text-muted-foreground truncate\">\n Cached\n </span>\n </>\n ) : cacheStatus === 'MISS' && !isStale ? (\n <>\n <div className=\"h-1.5 w-1.5 rounded-full bg-accent2 flex-shrink-0\" />\n <span className=\"text-xs text-muted-foreground truncate\">\n Fresh {FORMAT_LABEL.toLowerCase()}\n </span>\n </>\n ) : isStale ? (\n <>\n <div className=\"h-1.5 w-1.5 rounded-full bg-warning flex-shrink-0\" />\n <span className=\"text-xs text-warning truncate\">\n Outdated — click Run\n </span>\n {editTimestamp &&\n hasUnsyncedEdits &&\n !isGenerating &&\n !hasValidationErrors &&\n autoReload &&\n renderingLibrary === 'docxjs' && (\n <DebounceCountdown\n editTimestamp={editTimestamp}\n debounceMs={saveDocumentDebounceWait + 200}\n />\n )}\n </>\n ) : null}\n </div>\n {!isStale && cacheHitRate && cacheHitRate !== '0.0%' && (\n <span className=\"text-xs text-muted-foreground flex-shrink-0 ml-2\">\n {cacheHitRate} hit rate\n </span>\n )}\n </div>\n )\n );\n })()}\n {/* Warnings Panel */}\n <WarningsPanel warnings={warnings} className=\"mx-3 my-2\" />\n <UnavailableThemeWarning className=\"mx-3 my-2\" />\n {/* Generation Error — centered in preview area */}\n {globalError && !isGenerating ? (\n <div className=\"flex-1 flex items-center justify-center p-6\">\n <div className=\"max-w-md rounded-sm border-l-4 border-l-destructive bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n <p className=\"font-medium mb-1\">Generation failed</p>\n <p className=\"text-xs text-destructive/80 break-words\">\n {globalError}\n </p>\n </div>\n </div>\n ) : (\n <PreviewFrameMemoized\n ref={iframeRef}\n isLoading={Boolean(isRendering)}\n iframeSrc={iframeSrc}\n iframeSrcDoc={iframeSrcDoc}\n isGenerating={(() => {\n const willAutoBuild = autoReload && renderingLibrary === 'docxjs';\n const isSwitchingDoc =\n activeTab &&\n name &&\n activeTab !== name &&\n documentTypes[activeTab] !== 'application/json+theme';\n return (\n Boolean(isGenerating) ||\n Boolean(willAutoBuild && isSwitchingDoc)\n );\n })()}\n generationProgress={(() => {\n const willAutoBuild = autoReload && renderingLibrary === 'docxjs';\n const isSwitchingDoc =\n activeTab &&\n name &&\n activeTab !== name &&\n documentTypes[activeTab] !== 'application/json+theme';\n return willAutoBuild && isSwitchingDoc && !isGenerating\n ? {\n stage: 'parsing' as const,\n message: `Building preview for ${activeTab}...`,\n }\n : generationProgress;\n })()}\n generationDocumentText={editorDocumentText ?? text}\n generationStartedAt={generationStartedAt}\n onCancelGeneration={cancelGeneration}\n />\n )}\n </div>\n\n {/* Cache Metrics Dialog */}\n <Dialog open={showCacheMetrics} onOpenChange={setShowCacheMetrics}>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Cache Performance</DialogTitle>\n </DialogHeader>\n <CacheMetrics />\n </DialogContent>\n </Dialog>\n </>\n );\n}\n"],"file":"assets/preview-D3QYaLPp.js"}
|