@danhachuel/pandanews 0.4.3 → 0.4.5

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.
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.left-1{left:.25rem}.left-11{left:2.75rem}.left-9{left:2.25rem}.top-1{top:.25rem}.z-50{z-index:50}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-40{height:10rem}.h-44{height:11rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-auto{height:auto}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-20{width:5rem}.w-40{width:10rem}.w-44{width:11rem}.w-6{width:1.5rem}.w-60{width:15rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-2xl{max-width:42rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-400\/40{border-color:#fbbf2466}.border-panda\/40{border-color:#22c55e66}.border-red-400\/40{border-color:#f8717166}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-black\/60{background-color:#0009}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-night{--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1))}.bg-panda{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-panda\/10{background-color:#22c55e1a}.bg-panda\/15{background-color:#22c55e26}.bg-panda\/30{background-color:#22c55e4d}.bg-panda\/70{background-color:#22c55eb3}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-sky-100{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-300{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pr-4{padding-right:1rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-panda{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-panda-dark{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-sky-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.line-through{text-decoration-line:line-through}.placeholder-slate-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.placeholder-slate-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.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)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}body{--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1));font-family:Inter,system-ui,sans-serif;--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}html:not(.dark) body{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.last\:border-0:last-child{border-width:0px}.hover\:border-slate-400:hover{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.hover\:bg-panda-dark:hover{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:text-slate-800:hover{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-panda:focus{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.dark\:border-slate-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-slate-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity, 1))}.dark\:bg-amber-500\/15:is(.dark *){background-color:#f59e0b26}.dark\:bg-card:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(16 26 44 / var(--tw-bg-opacity, 1))}.dark\:bg-emerald-500\/15:is(.dark *){background-color:#10b98126}.dark\:bg-night:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1))}.dark\:bg-red-500\/15:is(.dark *){background-color:#ef444426}.dark\:bg-sky-500\/15:is(.dark *){background-color:#0ea5e926}.dark\:bg-slate-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-700\/60:is(.dark *){background-color:#33415599}.dark\:bg-slate-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:text-amber-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.dark\:text-emerald-400:is(.dark *){--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.dark\:text-panda:is(.dark *){--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-sky-400:is(.dark *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.dark\:text-slate-200:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-slate-500:is(.dark *){--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:text-slate-600:is(.dark *){--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:hover\:border-slate-500:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(100 116 139 / var(--tw-border-opacity, 1))}.dark\:hover\:bg-slate-800\/60:hover:is(.dark *){background-color:#1e293b99}.dark\:hover\:text-slate-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}@media (min-width: 640px){.sm\:inline{display:inline}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1280px){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}
@@ -8,8 +8,8 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
10
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
11
- <script type="module" crossorigin src="/assets/index-BLjBdAFC.js"></script>
12
- <link rel="stylesheet" crossorigin href="/assets/index-CUCWGfn9.css">
11
+ <script type="module" crossorigin src="/assets/index-BA6xr3Hb.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/assets/index-tVJXH-iW.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/pandanews",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "SaaS local de criação e automação de múltiplos blogs de notícias com IA (FastAPI + React + Tailwind).",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/scripts/build.js CHANGED
@@ -15,12 +15,18 @@ export async function runBuild() {
15
15
  return;
16
16
  }
17
17
  const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
18
+ // Regra permanente (AGENTS.md): NENHUM spawn pode abrir janela de console
19
+ // no computador do usuário. No Windows o filho nasce com CREATE_NO_WINDOW
20
+ // (windowsHide: true) — com `shell: true` o wrapper cmd.exe também nasce
21
+ // oculto, sem piscar tela preta. O stdio segue 'inherit': a saída fica no
22
+ // console que o usuário já abriu.
23
+ const SILENT_WINDOWS = { windowsHide: true };
18
24
  console.log('Instalando dependências do frontend...');
19
25
  // shell: true — obrigatório para .cmd no Windows (Node >= 18)
20
- const install = spawnSync(npmCmd, ['install'], { cwd: frontendDir, stdio: 'inherit', shell: true });
26
+ const install = spawnSync(npmCmd, ['install'], { cwd: frontendDir, stdio: 'inherit', shell: true, ...SILENT_WINDOWS });
21
27
  if (install.status !== 0) throw new Error('Falha ao instalar dependências do frontend.');
22
28
  console.log('Compilando o frontend...');
23
- const build = spawnSync(npmCmd, ['run', 'build'], { cwd: frontendDir, stdio: 'inherit', shell: true });
29
+ const build = spawnSync(npmCmd, ['run', 'build'], { cwd: frontendDir, stdio: 'inherit', shell: true, ...SILENT_WINDOWS });
24
30
  if (build.status !== 0) throw new Error('Falha ao compilar o frontend.');
25
31
  console.log('Frontend compilado em frontend/dist.');
26
32
  }
@@ -21,6 +21,20 @@ import fse from 'fs-extra';
21
21
  const __dirname = fileURLToPath(new URL('.', import.meta.url));
22
22
  export const PKG_ROOT = join(__dirname, '..');
23
23
 
24
+ // ------------------------------------------------------------------------
25
+ // Regra permanente (AGENTS.md): é PROIBIDO abrir janelas de terminal (CMD,
26
+ // PowerShell, console Python) no computador do usuário. Todo processo filho
27
+ // lançado pelo instalador nasce no Windows com `windowsHide: true`, que aplica
28
+ // a flag CREATE_NO_WINDOW — nenhuma tela preta aparece.
29
+ //
30
+ // `detached: true` NÃO é usado aqui de propósito: essas chamadas são curtas
31
+ // (tar/venv/pip) e o `stdio: 'inherit'` mantém o progresso no console que o
32
+ // usuário JÁ abriu. Com CREATE_NO_WINDOW o filho escreve nos handles herdados
33
+ // sem alocar uma janela extra. O teste scripts/test-start-isolation.mjs varre
34
+ // este arquivo e falha o build se qualquer spawn perder o windowsHide.
35
+ // ------------------------------------------------------------------------
36
+ const SILENT_WINDOWS = { windowsHide: true };
37
+
24
38
  const PYTHON_VERSION = '3.12.7';
25
39
  const PYTHON_RELEASE = '20241016';
26
40
 
@@ -152,7 +166,7 @@ async function downloadPython(home, platform) {
152
166
  const buf = Buffer.from(await res.arrayBuffer());
153
167
  writeFileSync(archive, buf);
154
168
  console.log(`Download concluído (${(buf.length / 1024 / 1024).toFixed(1)} MB). Extraindo...`);
155
- const tar = spawnSync('tar', ['-xzf', archive, '-C', runtimeDir]);
169
+ const tar = spawnSync('tar', ['-xzf', archive, '-C', runtimeDir], SILENT_WINDOWS);
156
170
  if (tar.status !== 0) throw new Error('Falha ao extrair o Python portátil (tar).');
157
171
  if (!existsSync(pythonBin(home))) {
158
172
  throw new Error('Extração do Python concluída, mas o binário não foi encontrado.');
@@ -162,7 +176,10 @@ async function downloadPython(home, platform) {
162
176
 
163
177
  function createVenv(home) {
164
178
  console.log('Criando virtualenv...');
165
- const venv = spawnSync(pythonBin(home), ['-m', 'venv', join(home, '.runtime', 'venv')], { stdio: 'inherit' });
179
+ const venv = spawnSync(pythonBin(home), ['-m', 'venv', join(home, '.runtime', 'venv')], {
180
+ stdio: 'inherit',
181
+ ...SILENT_WINDOWS,
182
+ });
166
183
  if (venv.status !== 0) throw new Error('Falha ao criar o virtualenv.');
167
184
  if (!existsSync(venvBin(home))) throw new Error('Virtualenv criado, mas o binário não foi encontrado.');
168
185
  }
@@ -173,7 +190,7 @@ function installDeps(home) {
173
190
  const pip = spawnSync(
174
191
  venvBin(home),
175
192
  ['-m', 'pip', 'install', '--disable-pip-version-check', '-r', req],
176
- { stdio: 'inherit' },
193
+ { stdio: 'inherit', ...SILENT_WINDOWS },
177
194
  );
178
195
  if (pip.status !== 0) throw new Error('Falha ao instalar as dependências do backend.');
179
196
  }
@@ -1,20 +1,134 @@
1
- // Teste de regressão do isolamento de processos do launcher (scripts/start.js).
1
+ // Teste de regressão do isolamento de processos (regra permanente do AGENTS.md):
2
+ // NENHUM spawn/exec do launcher/instalador pode abrir janela de terminal (CMD,
3
+ // PowerShell, console Python) no computador do usuário.
2
4
  //
3
- // Falha se as flags de isolamento forem removidas: detached (novo grupo de
4
- // processos — imune a Ctrl+C do console no Windows), windowsHide (sem janela
5
- // fantasma), stdio no arquivo (backend sobrevive ao terminal), unref e o
6
- // arquivo backend.pid (encerramento gracioso por código).
5
+ // Cobre TODOS os pontos de entrada:
6
+ // scripts/start.js — backend uvicorn + taskkill
7
+ // scripts/install.js — tar / venv / pip
8
+ // scripts/build.js — npm.cmd install e run build (shell: true)
9
+ // bin/cli.js — despacho de comandos
10
+ // backend/**/*.py — nenhuma chamada direta a subprocess/os.system
7
11
  //
8
12
  // Roda em qualquer plataforma, inclusive no CI (Linux/ubuntu) — sem exigir o
9
13
  // runtime Python completo.
10
- import { readFileSync } from 'node:fs';
14
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
11
15
  import { join, dirname } from 'node:path';
12
16
  import { fileURLToPath } from 'node:url';
13
17
 
14
18
  const root = join(dirname(fileURLToPath(import.meta.url)), '..');
15
- const src = readFileSync(join(root, 'scripts', 'start.js'), 'utf8');
16
19
 
17
- const verificacoes = [
20
+ const falhas = [];
21
+
22
+ function assert(condicao, mensagem) {
23
+ console.log(`${condicao ? 'PASS' : 'FAIL'} — ${mensagem}`);
24
+ if (!condicao) falhas.push(mensagem);
25
+ }
26
+
27
+ // ---------------------------------------------------------------- utilidades
28
+
29
+ // Extrai o conteúdo entre delimitadores balanceados, começando em `inicio`
30
+ // (índice do delimitador de abertura). Ignora delimitadores dentro de strings.
31
+ function ateOFechamento(src, inicio, abre, fecha) {
32
+ let profundidade = 1;
33
+ let aspa = null;
34
+ let escapando = false;
35
+ for (let i = inicio + 1; i < src.length; i++) {
36
+ const c = src[i];
37
+ if (escapando) {
38
+ escapando = false;
39
+ continue;
40
+ }
41
+ if (c === '\\') {
42
+ escapando = true;
43
+ continue;
44
+ }
45
+ if (aspa) {
46
+ if (c === aspa) aspa = null;
47
+ continue;
48
+ }
49
+ if (c === "'" || c === '"' || c === '`') {
50
+ aspa = c;
51
+ continue;
52
+ }
53
+ if (c === abre) profundidade += 1;
54
+ else if (c === fecha) {
55
+ profundidade -= 1;
56
+ if (profundidade === 0) return src.slice(inicio + 1, i);
57
+ }
58
+ }
59
+ return src.slice(inicio + 1);
60
+ }
61
+
62
+ // Texto completo dos argumentos de uma chamada, a partir do '(' encontrado.
63
+ function argumentosDaChamada(src, indiceAbre) {
64
+ return ateOFechamento(src, indiceAbre, '(', ')');
65
+ }
66
+
67
+ // Objetos literais de nível de módulo (const NOME = { ... }) — servem para
68
+ // resolver spreads como `...SILENT_WINDOWS` dentro das opções de spawn.
69
+ function constantesDeModulo(src) {
70
+ const mapa = new Map();
71
+ const regex = /const\s+([A-Za-z_$][\w$]*)\s*=\s*\{/g;
72
+ let m;
73
+ while ((m = regex.exec(src)) !== null) {
74
+ const inicioChaves = m.index + m[0].length - 1;
75
+ mapa.set(m[1], ateOFechamento(src, inicioChaves, '{', '}'));
76
+ }
77
+ return mapa;
78
+ }
79
+
80
+ // Uma referência a constante (solta ou via spread `...NOME`) é silenciosa
81
+ // apenas se a constante NOME trouxer windowsHide.
82
+ function referenciaConstanteSilenciosa(argTexto, constantes) {
83
+ const regex = /([A-Za-z_$][\w$]*)/g;
84
+ let m;
85
+ while ((m = regex.exec(argTexto)) !== null) {
86
+ const definicao = constantes.get(m[1]);
87
+ if (definicao && /windowsHide:\s*true/.test(definicao)) return true;
88
+ }
89
+ return false;
90
+ }
91
+
92
+ // ------------------------------------------------------------ varredura JS
93
+
94
+ const PONTOS_DE_ENTRADA_JS = ['scripts/start.js', 'scripts/install.js', 'scripts/build.js', 'bin/cli.js'];
95
+
96
+ for (const relativo of PONTOS_DE_ENTRADA_JS) {
97
+ const caminho = join(root, relativo);
98
+ if (!existsSync(caminho)) {
99
+ assert(false, `${relativo} — arquivo ausente`);
100
+ continue;
101
+ }
102
+ const src = readFileSync(caminho, 'utf8');
103
+ const constantes = constantesDeModulo(src);
104
+
105
+ const chamadas = [...src.matchAll(/\b(spawn|spawnSync|exec|execSync|execFile|execFileSync)\s*\(/g)];
106
+ let silenciosas = 0;
107
+ for (const chamada of chamadas) {
108
+ const indiceAbre = chamada.index + chamada[0].length - 1;
109
+ const texto = argumentosDaChamada(src, indiceAbre);
110
+ if (/windowsHide:\s*true/.test(texto) || referenciaConstanteSilenciosa(texto, constantes)) {
111
+ silenciosas += 1;
112
+ } else {
113
+ const marca = `${chamada[1]}(${texto.slice(0, 60).replace(/\s+/g, ' ')}…)`;
114
+ assert(false, `${relativo} — ${marca} sem windowsHide: true (abre janela de console no usuário)`);
115
+ }
116
+ }
117
+ if (chamadas.length === 0) {
118
+ assert(true, `${relativo} — nenhuma chamada de processo direta (sem risco de janela de console)`);
119
+ } else {
120
+ assert(
121
+ silenciosas === chamadas.length,
122
+ `${relativo} — ${silenciosas}/${chamadas.length} chamadas de processo com windowsHide: true`,
123
+ );
124
+ }
125
+ }
126
+
127
+ // ------------------------------------------- isolamento do backend (start.js)
128
+
129
+ const startSrc = readFileSync(join(root, 'scripts', 'start.js'), 'utf8');
130
+
131
+ for (const [regex, descricao] of [
18
132
  [/detached:\s*true/, 'detached: true — grupo de processos próprio (CREATE_NEW_PROCESS_GROUP no Windows)'],
19
133
  [/windowsHide:\s*true/, 'windowsHide: true — sem janela de console fantasma'],
20
134
  [/stdio:\s*\['ignore',\s*logFd,\s*logFd\]/, "stdio: ['ignore', logFd, logFd] — saída do backend no arquivo (fd)"],
@@ -24,32 +138,81 @@ const verificacoes = [
24
138
  [/\.unref\(\)/, 'unref() — launcher não acopla o ciclo de vida ao backend'],
25
139
  [/taskkill/, 'encerramento no Windows via taskkill /PID /T (árvore de processos)'],
26
140
  [/process\.kill/, 'encerramento no Unix via signal no grupo de processos'],
141
+ ]) {
142
+ assert(regex.test(startSrc), descricao);
143
+ }
144
+
145
+ // Uvicorn em produção JAMAIS com --reload/--workers: cada worker é um processo
146
+ // filho extra, que no Windows pode alocar console próprio e ignorar as flags
147
+ // do processo pai.
148
+ const uvicornExtras = startSrc.match(/['"]--(?:reload|workers)['"]/g);
149
+ assert(
150
+ !uvicornExtras,
151
+ `uvicorn sem --reload/--workers (nenhum processo filho extra no Windows)${
152
+ uvicornExtras ? ` — encontrado: ${uvicornExtras.join(', ')}` : ''
153
+ }`,
154
+ );
155
+
156
+ // ------------------------------------------------ varredura Python (backend)
157
+
158
+ const PROC_HELPER = join(root, 'backend', 'core', 'proc.py');
159
+ assert(existsSync(PROC_HELPER), 'backend/core/proc.py — helper silencioso existe (ponto único de subprocesso)');
160
+ if (existsSync(PROC_HELPER)) {
161
+ const procSrc = readFileSync(PROC_HELPER, 'utf8');
162
+ assert(/CREATE_NO_WINDOW\s*=\s*0x08000000/.test(procSrc), 'CREATE_NO_WINDOW = 0x08000000 definido no helper');
163
+ assert(/def run_silent_process/.test(procSrc), 'run_silent_process disponível no helper');
164
+ assert(/creationflags/.test(procSrc), 'helper aplica creationflags no Windows');
165
+ }
166
+
167
+ // Lista recursiva dos .py do backend (sem __pycache__).
168
+ function listarPy(diretorio, acumulador = []) {
169
+ for (const entrada of readdirSync(diretorio, { withFileTypes: true })) {
170
+ if (entrada.name === '__pycache__') continue;
171
+ const caminho = join(diretorio, entrada.name);
172
+ if (entrada.isDirectory()) listarPy(caminho, acumulador);
173
+ else if (entrada.name.endsWith('.py')) acumulador.push(caminho);
174
+ }
175
+ return acumulador;
176
+ }
177
+
178
+ const PADROES_PROIBIDOS = [
179
+ [/subprocess\.run\(/, 'subprocess.run('],
180
+ [/subprocess\.Popen\(/, 'subprocess.Popen('],
181
+ [/subprocess\.call\(/, 'subprocess.call('],
182
+ [/subprocess\.check_output\(/, 'subprocess.check_output('],
183
+ [/subprocess\.check_call\(/, 'subprocess.check_call('],
184
+ [/os\.system\(/, 'os.system('],
185
+ [/os\.popen\(/, 'os.popen('],
27
186
  ];
28
187
 
29
- let falhas = 0;
30
- for (const [regex, descricao] of verificacoes) {
31
- const ok = regex.test(src);
32
- console.log(`${ok ? 'PASS' : 'FAIL'} — ${descricao}`);
33
- if (!ok) falhas += 1;
34
- }
35
-
36
- // Regra permanente (AGENTS.md): NENHUMA spawn do launcher pode abrir janela de
37
- // console — toda chamada spawn/spawnSync precisa de windowsHide E detached.
38
- const chamadasSpawn = [...src.matchAll(/\bspawn(?:Sync)?\(/g)];
39
- for (const chamada of chamadasSpawn) {
40
- const trecho = src.slice(chamada.index, chamada.index + 700);
41
- const temJanelaOculta = /windowsHide:\s*true/.test(trecho);
42
- const temGrupoIsolado = /detached:\s*true/.test(trecho);
43
- if (temJanelaOculta && temGrupoIsolado) {
44
- console.log('PASS — spawn com windowsHide + detached (sem janela de console no usuário)');
45
- } else {
46
- console.log(`FAIL — spawn sem windowsHide/detached: ${trecho.slice(0, 80).replace(/\n/g, ' ')}…`);
47
- falhas += 1;
188
+ const backendDir = join(root, 'backend');
189
+ let arquivosPy = 0;
190
+ let diretasProibidas = 0;
191
+ if (existsSync(backendDir)) {
192
+ for (const arquivo of listarPy(backendDir)) {
193
+ if (arquivo.endsWith(join('core', 'proc.py'))) continue; // helper autorizado
194
+ arquivosPy += 1;
195
+ const conteudo = readFileSync(arquivo, 'utf8');
196
+ const relativo = arquivo.slice(root.length + 1);
197
+ for (const [regex, rotulo] of PADROES_PROIBIDOS) {
198
+ if (regex.test(conteudo)) {
199
+ diretasProibidas += 1;
200
+ assert(false, `${relativo} — uso direto de ${rotulo} sem CREATE_NO_WINDOW (use backend.core.proc)`);
201
+ }
202
+ }
48
203
  }
49
204
  }
205
+ assert(arquivosPy > 0, `backend/ — ${arquivosPy} arquivos .py varridos`);
206
+ assert(
207
+ diretasProibidas === 0,
208
+ 'nenhuma chamada direta a subprocess/os.system no backend (todas via helper silencioso)',
209
+ );
210
+
211
+ // -------------------------------------------------------------- veredicto
50
212
 
51
- if (falhas > 0) {
52
- console.error(`Isolamento de processos: ${falhas} verificação(ões) falharam.`);
53
- process.exit(1);
213
+ if (falhas.length === 0) {
214
+ console.log('Isolamento de processos: todas as verificações passaram.');
215
+ process.exit(0);
54
216
  }
55
- console.log('Isolamento de processos: todas as verificações passaram.');
217
+ console.error(`Isolamento de processos: ${falhas.length} verificação(ões) falharam.`);
218
+ process.exit(1);
@@ -1 +0,0 @@
1
- *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.left-1{left:.25rem}.left-11{left:2.75rem}.left-9{left:2.25rem}.top-1{top:.25rem}.z-50{z-index:50}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-40{height:10rem}.h-44{height:11rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-auto{height:auto}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-20{width:5rem}.w-40{width:10rem}.w-44{width:11rem}.w-6{width:1.5rem}.w-60{width:15rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-2xl{max-width:42rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-t-md{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-400\/40{border-color:#fbbf2466}.border-panda\/40{border-color:#22c55e66}.border-red-400\/40{border-color:#f8717166}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-black\/60{background-color:#0009}.bg-emerald-100{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.bg-night{--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1))}.bg-panda{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-panda\/10{background-color:#22c55e1a}.bg-panda\/15{background-color:#22c55e26}.bg-panda\/30{background-color:#22c55e4d}.bg-panda\/70{background-color:#22c55eb3}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-sky-100{--tw-bg-opacity: 1;background-color:rgb(224 242 254 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-300{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pr-4{padding-right:1rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-emerald-300{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-panda{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-panda-dark{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-sky-700{--tw-text-opacity: 1;color:rgb(3 105 161 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.line-through{text-decoration-line:line-through}.placeholder-slate-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.placeholder-slate-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.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)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}body{--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1));font-family:Inter,system-ui,sans-serif;--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}html:not(.dark) body{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.last\:border-0:last-child{border-width:0px}.hover\:border-slate-400:hover{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.hover\:bg-panda-dark:hover{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:text-slate-800:hover{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-panda:focus{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.dark\:border-slate-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-slate-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(30 41 59 / var(--tw-border-opacity, 1))}.dark\:bg-amber-500\/15:is(.dark *){background-color:#f59e0b26}.dark\:bg-card:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(16 26 44 / var(--tw-bg-opacity, 1))}.dark\:bg-emerald-500\/15:is(.dark *){background-color:#10b98126}.dark\:bg-night:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(11 18 32 / var(--tw-bg-opacity, 1))}.dark\:bg-red-500\/15:is(.dark *){background-color:#ef444426}.dark\:bg-sky-500\/15:is(.dark *){background-color:#0ea5e926}.dark\:bg-slate-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-700\/60:is(.dark *){background-color:#33415599}.dark\:bg-slate-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:text-amber-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.dark\:text-emerald-400:is(.dark *){--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.dark\:text-panda:is(.dark *){--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-sky-400:is(.dark *){--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.dark\:text-slate-200:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-slate-500:is(.dark *){--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:text-slate-600:is(.dark *){--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:hover\:border-slate-500:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(100 116 139 / var(--tw-border-opacity, 1))}.dark\:hover\:bg-slate-800\/60:hover:is(.dark *){background-color:#1e293b99}.dark\:hover\:text-slate-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}@media (min-width: 640px){.sm\:inline{display:inline}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1280px){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}