outcrop 0.1.0 → 0.1.1

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 CHANGED
@@ -42,7 +42,7 @@ function writeSettings(file, s) {
42
42
  }
43
43
 
44
44
  // src/styles.gen.css
45
- var styles_gen_default = "*,:after,:before{--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:rgba(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:rgba(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: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-ui);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,pre,samp{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,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{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}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.detail-body h1,.detail-body h2,.detail-body h3,.detail-body h4{margin-top:1.25rem;margin-bottom:.375rem;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.detail-body h1:first-child,.detail-body h2:first-child,.detail-body h3:first-child,.detail-body h4:first-child{margin-top:0}.detail-body h1:is(.dark *),.detail-body h2:is(.dark *),.detail-body h3:is(.dark *),.detail-body h4:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body p{margin-top:.375rem;margin-bottom:.375rem;font-size:13px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body p:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body ul{margin-top:.375rem;margin-bottom:.375rem}.detail-body ul>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.detail-body ul{padding-left:1rem;font-size:13px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body ul:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body ul:not(.ordered)>li{list-style-type:disc}.detail-body li.check{margin-left:-1rem;display:flex;list-style-type:none;align-items:flex-start;gap:.5rem}.detail-body li.check .box{margin-top:.125rem;display:flex;height:15px;width:15px;flex-shrink:0;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));font-size:10px;line-height:1;--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.detail-body li.check .box:hover{--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.detail-body li.check .box:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.detail-body li.check .box:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.detail-body li.check.done{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));text-decoration-line:line-through}.detail-body li.check.done:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body li.check.done .box{border-color:rgba(16,185,129,.5);--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.detail-body li.check.done .box:is(.dark *){background-color:rgba(16,185,129,.1)}.detail-body ul.ordered>li{list-style-type:none}.detail-body code{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:1px .25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body code:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body pre{margin-top:.5rem;margin-bottom:.5rem;overflow-x:auto;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:.75rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body pre:is(.dark *){background-color:rgba(39,39,42,.8);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body .ref{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.detail-body .ref:hover{text-decoration-line:underline}.detail-body .ref:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.detail-body table{margin-top:.5rem;margin-bottom:.5rem;width:100%;border-collapse:collapse;font-size:12.5px}.detail-body th{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding-top:.25rem;padding-bottom:.25rem;padding-right:.75rem;text-align:left;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.detail-body th:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding-top:.375rem;padding-bottom:.375rem;padding-right:.75rem;vertical-align:top;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body td:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body a.mdlink{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.detail-body a.mdlink:hover{text-decoration-line:underline}.detail-body a.mdlink:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.doc-body h1{margin-bottom:.75rem;margin-top:.5rem;font-size:21px;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body h1:is(.dark *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity,1))}.doc-body h2{margin-bottom:.5rem;margin-top:1.75rem;border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding-bottom:.375rem;font-size:16px;font-weight:600;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body h2:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.doc-body h3{margin-bottom:.375rem;margin-top:1.25rem;font-size:13.5px;font-weight:600;--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.doc-body h3:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.doc-body h4{margin-bottom:.25rem;margin-top:1rem;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-body h4:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body p{margin-top:.5rem;margin-bottom:.5rem;font-size:13.5px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body p:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body ul{margin-top:.5rem;margin-bottom:.5rem}.doc-body ul>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.doc-body ul{padding-left:1.25rem;font-size:13.5px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body ul:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body ul:not(.ordered)>li{list-style-type:disc}.doc-body ul.ordered>li{list-style-type:none}.doc-body li.check{margin-left:-1.25rem;display:flex;list-style-type:none;align-items:flex-start;gap:.5rem}.doc-body li.check .box{margin-top:.25rem;display:flex;height:14px;width:14px;flex-shrink:0;align-items:center;justify-content:center;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));font-size:9px;line-height:1;--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.doc-body li.check .box:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.doc-body li.check.done{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));text-decoration-line:line-through}.doc-body li.check.done:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body code{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:1px .25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body code:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body pre{margin-top:.75rem;margin-bottom:.75rem;overflow-x:auto;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:.75rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body pre:is(.dark *){background-color:rgba(39,39,42,.8);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body table{margin-top:.75rem;margin-bottom:.75rem;width:100%;border-collapse:collapse;font-size:13px}.doc-body th{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));padding-top:.375rem;padding-bottom:.375rem;padding-right:1rem;text-align:left;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-body th:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;vertical-align:top;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body td:is(.dark *){border-color:rgba(39,39,42,.6);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body img{margin-left:auto;margin-right:auto;display:inline-block;height:auto;max-width:100%}.doc-body [align=center]{text-align:center}.doc-body [align=right]{text-align:right}.doc-body .ref,.doc-body a.mdlink{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.doc-body .ref:hover,.doc-body a.mdlink:hover{text-decoration-line:underline}.doc-body .ref:is(.dark *),.doc-body a.mdlink:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.doc-body .ref{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12.5px}.doc-body .mermaid{margin-top:1rem;margin-bottom:1rem;display:flex;justify-content:center;overflow-x:auto}.doc-body strong{font-weight:600;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body strong:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.detail-body hr,.doc-body hr{margin-top:1.5rem;margin-bottom:1.5rem;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.detail-body hr:is(.dark *),.doc-body hr:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.doc-folder>summary{display:flex;cursor:pointer;list-style-type:none;align-items:center;gap:.375rem;border-radius:.375rem;padding:.25rem .5rem;font-size:13.5px;font-weight:600;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-folder>summary:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.doc-folder>summary:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.doc-folder>summary:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.doc-folder>summary::-webkit-details-marker{display:none}.doc-folder>summary:before{content:\"›\";display:inline-block;width:.5rem;flex-shrink:0;font-size:13px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-folder>summary:is(.dark *):before{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.doc-folder[open]>summary:before{transform:rotate(90deg)}.doc-folder-count{margin-left:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:10px;font-weight:400;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-folder-count:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.doc-folder+.doc-folder{margin-top:.375rem}.doc-link{margin-left:9px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:.375rem;border-left-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding:.25rem .5rem .25rem .625rem;font-size:12px;--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-link:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.doc-link:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-link:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.doc-link.active{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));font-weight:500;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-link.active:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}#doc-outline.empty{display:none}.outline-link{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-left-width:2px;border-color:transparent;padding:.25rem .25rem .25rem .625rem;font-size:12px;line-height:1.375;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.outline-link:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.outline-link:is(.dark *){--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.outline-link:hover:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.outline-link.lvl-2{padding-left:1.25rem}.outline-link.lvl-3{padding-left:2rem;font-size:11.5px}.outline-link.active{--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));font-weight:500;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.outline-link.active:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}#doc-sidebar.collapsed,#doc-sidebar.collapsed+.sidebar-resizer{display:none!important}#search-results mark{border-radius:.125rem;--tw-bg-opacity:1;background-color:rgb(var(--accent-200)/var(--tw-bg-opacity,1));padding-left:.125rem;padding-right:.125rem;font-weight:500;--tw-text-opacity:1;color:rgb(var(--accent-950)/var(--tw-text-opacity,1))}#search-results mark:is(.dark *){background-color:rgb(var(--accent-600)/.5);--tw-text-opacity:1;color:rgb(var(--accent-100)/var(--tw-text-opacity,1))}::highlight(doc-search){background-color:rgb(var(--accent-300));color:rgb(var(--accent-950))}.dark ::highlight(doc-search){background-color:rgb(var(--accent-600));color:#fff}::highlight(doc-match){background-color:rgb(var(--accent-500));color:#fff}.dark ::highlight(doc-match){background-color:rgb(var(--accent-300));color:rgb(var(--accent-950))}.swatch{height:1.5rem;width:1.5rem;border-radius:9999px;border-width:2px;border-color:transparent;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgb(228 228 231/var(--tw-ring-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.swatch:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.swatch:is(.dark *){--tw-ring-opacity:1;--tw-ring-color:rgb(63 63 70/var(--tw-ring-opacity,1))}.swatch.active{--tw-border-opacity:1;border-color:rgb(24 24 27/var(--tw-border-opacity,1))}.swatch.active:is(.dark *){--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.swatch-violet{background-color:#8b5cf6}.swatch-blue{background-color:#3b82f6}.swatch-emerald{background-color:#10b981}.swatch-amber{background-color:#f59e0b}.swatch-rose{background-color:#f43f5e}.pick{flex:1 1 0%;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:.25rem .5rem;font-size:12px;--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.pick:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.pick:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.pick:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.pick.active{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(var(--accent-700)/var(--tw-text-opacity,1))}.pick.active:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));background-color:rgb(var(--accent-500)/.1);--tw-text-opacity:1;color:rgb(var(--accent-300)/var(--tw-text-opacity,1))}.theme-opt.theme-active{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(var(--accent-700)/var(--tw-text-opacity,1))}.theme-opt.theme-active:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));background-color:rgb(var(--accent-500)/.1);--tw-text-opacity:1;color:rgb(var(--accent-300)/var(--tw-text-opacity,1))}.set-group{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.set-group:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.set-group>summary{display:flex;cursor:pointer;list-style-type:none;align-items:center;gap:.5rem;padding-top:.625rem;padding-bottom:.625rem;font-size:12.5px;font-weight:500;--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.set-group>summary:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.set-group>summary::-webkit-details-marker{display:none}.set-group>summary:after{content:\"›\";margin-left:auto;font-size:15px;line-height:1;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.set-group>summary:is(.dark *):after{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.set-group[open]>summary:after{transform:rotate(90deg)}.set-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:400;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.set-sub:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.set-row{display:flex;align-items:flex-start;gap:.75rem;padding-top:.375rem;padding-bottom:.375rem}.set-label{width:72px;flex-shrink:0;padding-top:.375rem;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.set-label:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}#sheet.fullscreen{max-width:none}#sheet.fullscreen #sheet-content{margin-left:auto;margin-right:auto;max-width:42rem}.task-card{width:100%;cursor:pointer;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1));padding:.625rem .75rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.task-card:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.task-card:focus-visible{outline-style:solid;outline-width:2px;outline-offset:1px;outline-color:rgb(var(--accent-500)/1)}.task-card:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.task-card:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1))}.card-id{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-id:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.card-title{font-size:13px;font-weight:500;line-height:1.375;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.card-title:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.card-progress{margin-left:auto;display:inline-flex;align-items:center;gap:.375rem;font-size:10px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-progress:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.epic-chip{border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:1px .375rem;font-size:10px;font-weight:500;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.epic-chip:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.epic-chip:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.epic-chip:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.prio{display:inline-flex;align-items:center;gap:.25rem;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.prio:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.prio-label{font-size:10px;font-weight:500;letter-spacing:.025em}.dep-chip{display:inline-flex;align-items:center;gap:.25rem;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:1px .375rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:10px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dep-chip:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dep-chip:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.dep-chip:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dep-chip.done{border-color:transparent;--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.dep-chip.done:hover{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.dep-chip.done:is(.dark *){background-color:rgba(16,185,129,.1);--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.dep-chip.done:hover:is(.dark *){background-color:rgba(16,185,129,.2)}.backlink-row{display:flex;width:100%;align-items:center;gap:.5rem;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding:.375rem .625rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.backlink-row:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.backlink-row:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.backlink-row:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.epic-row{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;border-radius:.375rem;padding:.375rem .5rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.epic-row:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.epic-row:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.epic-row.epic-active{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.epic-row.epic-active:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}#sidebar>*{flex-shrink:0}#sidebar.collapsed,#sidebar.collapsed+.sidebar-resizer{display:none!important}section.drop-target{background-color:rgb(var(--accent-50)/.6);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-inset:inset;--tw-ring-opacity:1;--tw-ring-color:rgb(var(--accent-300)/var(--tw-ring-opacity,1))}section.drop-target:is(.dark *){background-color:rgb(var(--accent-500)/.05);--tw-ring-color:rgb(var(--accent-500)/0.4)}.task-card.\\!dragging,.task-card.dragging{opacity:.4}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-top-0\\.5{top:-.125rem}.bottom-3{bottom:.75rem}.bottom-5{bottom:1.25rem}.left-1{left:.25rem}.left-1\\/2{left:50%}.left-3{left:.75rem}.left-44{left:11rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.top-0{top:0}.top-4{top:1rem}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.z-\\[60\\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.-ml-0\\.5{margin-left:-.125rem}.mb-1{margin-bottom:.25rem}.mb-1\\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-2\\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-8{margin-bottom:2rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1\\.5{margin-right:.375rem}.mr-16{margin-right:4rem}.mt-1{margin-top:.25rem}.mt-1\\.5{margin-top:.375rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\\.5{height:.375rem}.h-12{height:3rem}.h-2{height:.5rem}.h-3\\.5{height:.875rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-\\[calc\\(\\(100vh\\/var\\(--zoom\\)\\)-3rem\\)\\]{height:calc(100vh/var(--zoom) - 3rem)}.h-\\[calc\\(100vh\\/var\\(--zoom\\)\\)\\]{height:calc(100vh/var(--zoom))}.h-full{height:100%}.min-h-\\[60px\\]{min-height:60px}.w-1{width:.25rem}.w-1\\.5{width:.375rem}.w-2{width:.5rem}.w-3\\.5{width:.875rem}.w-44{width:11rem}.w-56{width:14rem}.w-60{width:15rem}.w-\\[290px\\]{width:290px}.w-full{width:100%}.min-w-0{min-width:0}.max-w-3xl{max-width:48rem}.max-w-\\[460px\\]{max-width:460px}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\\/2{--tw-translate-x:-50%}.-translate-x-1\\/2,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-col-resize{cursor:col-resize}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\\[90px_1fr\\]{grid-template-columns:90px 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-y-1\\.5{row-gap:.375rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-zinc-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(228 228 231/var(--tw-divide-opacity,1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.border-y{border-top-width:1px}.border-b,.border-y{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-rose-300{--tw-border-opacity:1;border-color:rgb(253 164 175/var(--tw-border-opacity,1))}.border-rose-500\\/70{border-color:rgba(244,63,94,.7)}.border-zinc-100{--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.border-zinc-200{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.bg-accent-50{--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1))}.bg-accent-600{--tw-bg-opacity:1;background-color:rgb(var(--accent-600)/var(--tw-bg-opacity,1))}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-black\\/20{background-color:rgba(0,0,0,.2)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-rose-50{--tw-bg-opacity:1;background-color:rgb(255 241 242/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))}.bg-zinc-100{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.bg-zinc-300{--tw-bg-opacity:1;background-color:rgb(212 212 216/var(--tw-bg-opacity,1))}.bg-zinc-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.bg-zinc-900{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.p-0\\.5{padding:.125rem}.p-1{padding:.25rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-96{padding:24rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\\.5{padding-left:.375rem;padding-right:.375rem}.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-8{padding-left:2rem;padding-right:2rem}.py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\\.5{padding-top:.875rem;padding-bottom:.875rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-px{padding-top:1px;padding-bottom:1px}.pb-1{padding-bottom:.25rem}.pb-3{padding-bottom:.75rem}.pl-2\\.5{padding-left:.625rem}.pr-1{padding-right:.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:var(--font-ui)}.font-serif{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.text-\\[10\\.5px\\]{font-size:10.5px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[12\\.5px\\]{font-size:12.5px}.text-\\[12px\\]{font-size:12px}.text-\\[13px\\]{font-size:13px}.text-\\[16px\\]{font-size:16px}.text-\\[9\\.5px\\]{font-size:9.5px}.text-\\[9px\\]{font-size:9px}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.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)}.leading-5{line-height:1.25rem}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-accent-600{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-rose-500{--tw-text-opacity:1;color:rgb(244 63 94/var(--tw-text-opacity,1))}.text-rose-700{--tw-text-opacity:1;color:rgb(190 18 60/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-zinc-100{--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.text-zinc-800{--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.text-zinc-900{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-accent-600{accent-color:rgb(var(--accent-600)/1)}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;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-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}:root,html[data-accent=violet]{--accent-50:245 243 255;--accent-100:237 233 254;--accent-200:221 214 254;--accent-300:196 181 253;--accent-400:167 139 250;--accent-500:139 92 246;--accent-600:124 58 237;--accent-700:109 40 217;--accent-950:46 16 101}html[data-accent=blue]{--accent-50:239 246 255;--accent-100:219 234 254;--accent-200:191 219 254;--accent-300:147 197 253;--accent-400:96 165 250;--accent-500:59 130 246;--accent-600:37 99 235;--accent-700:29 78 216;--accent-950:23 37 84}html[data-accent=emerald]{--accent-50:236 253 245;--accent-100:209 250 229;--accent-200:167 243 208;--accent-300:110 231 183;--accent-400:52 211 153;--accent-500:16 185 129;--accent-600:5 150 105;--accent-700:4 120 87;--accent-950:2 44 34}html[data-accent=amber]{--accent-50:255 251 235;--accent-100:254 243 199;--accent-200:253 230 138;--accent-300:252 211 77;--accent-400:251 191 36;--accent-500:245 158 11;--accent-600:217 119 6;--accent-700:180 83 9;--accent-950:69 26 3}html[data-accent=rose]{--accent-50:255 241 242;--accent-100:255 228 230;--accent-200:254 205 211;--accent-300:253 164 175;--accent-400:251 113 133;--accent-500:244 63 94;--accent-600:225 29 72;--accent-700:190 18 60;--accent-950:76 5 25}:root,html[data-font=sans]{--font-ui:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif}html[data-font=serif]{--font-ui:ui-serif,Georgia,Cambria,\"Times New Roman\",Times,serif}html[data-font=mono]{--font-ui:ui-monospace,SFMono-Regular,\"SF Mono\",Menlo,Consolas,\"Liberation Mono\",monospace}:root{--zoom:1}html[data-size=compact]{--zoom:0.9}html[data-size=large]{--zoom:1.15}html[data-size=compact] body,html[data-size=large] body{zoom:var(--zoom)}@media (prefers-reduced-motion:no-preference){html.theme-anim,html.theme-anim *,html.theme-anim :after,html.theme-anim :before{transition:background-color .26s cubic-bezier(.4,0,.2,1),border-color .26s cubic-bezier(.4,0,.2,1),color .26s cubic-bezier(.4,0,.2,1),fill .26s cubic-bezier(.4,0,.2,1),stroke .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1)!important;transition-delay:0s!important}}.placeholder\\:text-zinc-400::-moz-placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.placeholder\\:text-zinc-400::placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.hover\\:border-zinc-300:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.hover\\:bg-accent-400\\/70:hover{background-color:rgb(var(--accent-400)/.7)}.hover\\:bg-accent-500:hover{--tw-bg-opacity:1;background-color:rgb(var(--accent-500)/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-100:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-200:hover{--tw-bg-opacity:1;background-color:rgb(228 228 231/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-50:hover{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.hover\\:text-zinc-600:hover{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.hover\\:text-zinc-900:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.hover\\:underline:hover{text-decoration-line:underline}.focus\\:border-accent-400:focus{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1))}.focus\\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:opacity-100:focus-visible{opacity:1}.active\\:bg-accent-400\\/70:active{background-color:rgb(var(--accent-400)/.7)}.group:hover .group-hover\\:opacity-100{opacity:1}@media (prefers-reduced-motion:no-preference){.motion-safe\\:transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.motion-safe\\:duration-200{transition-duration:.2s}}.dark\\:divide-zinc-800:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(39 39 42/var(--tw-divide-opacity,1))}.dark\\:border-rose-500\\/40:is(.dark *){border-color:rgba(244,63,94,.4)}.dark\\:border-zinc-700:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1))}.dark\\:border-zinc-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.dark\\:bg-accent-500\\/10:is(.dark *){background-color:rgb(var(--accent-500)/.1)}.dark\\:bg-amber-500\\/10:is(.dark *){background-color:rgba(245,158,11,.1)}.dark\\:bg-black\\/50:is(.dark *){background-color:rgba(0,0,0,.5)}.dark\\:bg-rose-500\\/10:is(.dark *){background-color:rgba(244,63,94,.1)}.dark\\:bg-zinc-100:is(.dark *){--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-950:is(.dark *){--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.dark\\:text-accent-400:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.dark\\:text-amber-400:is(.dark *){--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.dark\\:text-rose-300:is(.dark *){--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.dark\\:text-zinc-100:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.dark\\:text-zinc-200:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.dark\\:text-zinc-300:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dark\\:text-zinc-400:is(.dark *){--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.dark\\:text-zinc-50:is(.dark *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity,1))}.dark\\:text-zinc-500:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.dark\\:text-zinc-600:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:text-zinc-700:is(.dark *){--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.dark\\:text-zinc-900:is(.dark *){--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.dark\\:brightness-125:is(.dark *){--tw-brightness:brightness(1.25);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)}.dark\\:placeholder\\:text-zinc-600:is(.dark *)::-moz-placeholder{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:placeholder\\:text-zinc-600:is(.dark *)::placeholder{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:hover\\:border-zinc-600:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.dark\\:hover\\:bg-accent-500\\/60:hover:is(.dark *){background-color:rgb(var(--accent-500)/.6)}.dark\\:hover\\:bg-zinc-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(63 63 70/var(--tw-bg-opacity,1))}.dark\\:hover\\:bg-zinc-800:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}.dark\\:hover\\:bg-zinc-900:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.dark\\:hover\\:text-zinc-100:hover:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.dark\\:hover\\:text-zinc-300:hover:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dark\\:focus\\:border-accent-500:focus:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1))}.dark\\:active\\:bg-accent-500\\/60:active:is(.dark *){background-color:rgb(var(--accent-500)/.6)}@media (min-width:640px){.sm\\:block{display:block}}@media (min-width:768px){.md\\:block{display:block}.md\\:flex{display:flex}}@media (min-width:1024px){.lg\\:block{display:block}}.dark\\:\\[\\&\\>option\\]\\:bg-zinc-900>option:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}";
45
+ var styles_gen_default = "*,:after,:before{--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:rgba(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:rgba(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: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:\"\"}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-ui);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,pre,samp{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,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{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}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.detail-body h1,.detail-body h2,.detail-body h3,.detail-body h4{margin-top:1.25rem;margin-bottom:.375rem;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.detail-body h1:first-child,.detail-body h2:first-child,.detail-body h3:first-child,.detail-body h4:first-child{margin-top:0}.detail-body h1:is(.dark *),.detail-body h2:is(.dark *),.detail-body h3:is(.dark *),.detail-body h4:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body p{margin-top:.375rem;margin-bottom:.375rem;font-size:13px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body p:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body ul{margin-top:.375rem;margin-bottom:.375rem}.detail-body ul>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.detail-body ul{padding-left:1rem;font-size:13px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body ul:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body ul:not(.ordered)>li{list-style-type:disc}.detail-body li.check{margin-left:-1rem;display:flex;list-style-type:none;align-items:flex-start;gap:.5rem}.detail-body li.check .box{margin-top:.125rem;display:flex;height:15px;width:15px;flex-shrink:0;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));font-size:10px;line-height:1;--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.detail-body li.check .box:hover{--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.detail-body li.check .box:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.detail-body li.check .box:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(16 185 129/var(--tw-border-opacity,1))}.detail-body li.check.done{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));text-decoration-line:line-through}.detail-body li.check.done:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body li.check.done .box{border-color:rgba(16,185,129,.5);--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1))}.detail-body li.check.done .box:is(.dark *){background-color:rgba(16,185,129,.1)}.detail-body ul.ordered>li{list-style-type:none}.detail-body code{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:1px .25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body code:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body pre{margin-top:.5rem;margin-bottom:.5rem;overflow-x:auto;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:.75rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body pre:is(.dark *){background-color:rgba(39,39,42,.8);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body .ref{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.detail-body .ref:hover{text-decoration-line:underline}.detail-body .ref:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.detail-body table{margin-top:.5rem;margin-bottom:.5rem;width:100%;border-collapse:collapse;font-size:12.5px}.detail-body th{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding-top:.25rem;padding-bottom:.25rem;padding-right:.75rem;text-align:left;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.detail-body th:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.detail-body td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding-top:.375rem;padding-bottom:.375rem;padding-right:.75rem;vertical-align:top;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.detail-body td:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.detail-body a.mdlink{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.detail-body a.mdlink:hover{text-decoration-line:underline}.detail-body a.mdlink:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.doc-body h1{margin-bottom:.75rem;margin-top:.5rem;font-size:21px;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body h1:is(.dark *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity,1))}.doc-body h2{margin-bottom:.5rem;margin-top:1.75rem;border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding-bottom:.375rem;font-size:16px;font-weight:600;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body h2:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.doc-body h3{margin-bottom:.375rem;margin-top:1.25rem;font-size:13.5px;font-weight:600;--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.doc-body h3:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.doc-body h4{margin-bottom:.25rem;margin-top:1rem;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-body h4:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body p{margin-top:.5rem;margin-bottom:.5rem;font-size:13.5px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body p:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body ul{margin-top:.5rem;margin-bottom:.5rem}.doc-body ul>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.doc-body ul{padding-left:1.25rem;font-size:13.5px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body ul:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body ul:not(.ordered)>li{list-style-type:disc}.doc-body ul.ordered>li{list-style-type:none}.doc-body li.check{margin-left:-1.25rem;display:flex;list-style-type:none;align-items:flex-start;gap:.5rem}.doc-body li.check .box{margin-top:.25rem;display:flex;height:14px;width:14px;flex-shrink:0;align-items:center;justify-content:center;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));font-size:9px;line-height:1;--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.doc-body li.check .box:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.doc-body li.check.done{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));text-decoration-line:line-through}.doc-body li.check.done:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body code{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:1px .25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body code:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body pre{margin-top:.75rem;margin-bottom:.75rem;overflow-x:auto;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));padding:.75rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;line-height:1.625;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body pre:is(.dark *){background-color:rgba(39,39,42,.8);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.codeblock{position:relative}.copy-code{position:absolute;right:.5rem;top:.5rem;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1));padding:.25rem;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));opacity:0;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.copy-code:hover{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.copy-code:focus-visible{opacity:1}.copy-code:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.copy-code:hover:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.codeblock:hover .copy-code,.copy-code:focus-visible{opacity:1}@media (hover:none){.copy-code{opacity:1}}.copy-code.copied{border-color:rgba(16,185,129,.4);--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1));opacity:1}.copy-code.copied:is(.dark *){--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.codeblock>pre{margin-top:0;margin-bottom:0}.detail-body .codeblock,.doc-body .codeblock,.doc-body table{margin-top:.75rem;margin-bottom:.75rem}.doc-body table{width:100%;border-collapse:collapse;font-size:13px}.doc-body th{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));padding-top:.375rem;padding-bottom:.375rem;padding-right:1rem;text-align:left;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-body th:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.doc-body td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;vertical-align:top;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.doc-body td:is(.dark *){border-color:rgba(39,39,42,.6);--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.doc-body img{margin-left:auto;margin-right:auto;display:inline-block;height:auto;max-width:100%}.doc-body [align=center]{text-align:center}.doc-body [align=right]{text-align:right}.doc-body .ref,.doc-body a.mdlink{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.doc-body .ref:hover,.doc-body a.mdlink:hover{text-decoration-line:underline}.doc-body .ref:is(.dark *),.doc-body a.mdlink:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.doc-body .ref{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12.5px}.doc-body .mermaid{margin-top:1rem;margin-bottom:1rem;display:flex;justify-content:center;overflow-x:auto}.doc-body strong{font-weight:600;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-body strong:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.detail-body hr,.doc-body hr{margin-top:1.5rem;margin-bottom:1.5rem;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.detail-body hr:is(.dark *),.doc-body hr:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.doc-folder>summary{display:flex;cursor:pointer;list-style-type:none;align-items:center;gap:.375rem;border-radius:.375rem;padding:.25rem .5rem;font-size:13.5px;font-weight:600;--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-folder>summary:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.doc-folder>summary:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.doc-folder>summary:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.doc-folder>summary::-webkit-details-marker{display:none}.doc-folder>summary:before{content:\"›\";display:inline-block;width:.5rem;flex-shrink:0;font-size:13px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-folder>summary:is(.dark *):before{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.doc-folder[open]>summary:before{transform:rotate(90deg)}.doc-folder-count{margin-left:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:10px;font-weight:400;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-folder-count:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.doc-folder+.doc-folder{margin-top:.375rem}.doc-folder>summary{padding-left:calc(.5rem + var(--doc-depth, 0)*.75rem)}.doc-link{margin-left:9px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:.375rem;border-left-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding:.25rem .5rem .25rem .625rem;font-size:12px;--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.doc-link:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.doc-link:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.doc-link:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.doc-link{padding-left:calc(.625rem + (var(--doc-depth, 1) - 1)*.75rem)}.doc-link.active{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));font-weight:500;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.doc-link.active:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}#doc-outline.empty{display:none}.outline-link{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-left-width:2px;border-color:transparent;padding:.25rem .25rem .25rem .625rem;font-size:12px;line-height:1.375;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.outline-link:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.outline-link:is(.dark *){--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.outline-link:hover:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.outline-link.lvl-2{padding-left:1.25rem}.outline-link.lvl-3{padding-left:2rem;font-size:11.5px}.outline-link.active{--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));font-weight:500;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.outline-link.active:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}#doc-sidebar.collapsed,#doc-sidebar.collapsed+.sidebar-resizer{display:none!important}#search-results mark{border-radius:.125rem;--tw-bg-opacity:1;background-color:rgb(var(--accent-200)/var(--tw-bg-opacity,1));padding-left:.125rem;padding-right:.125rem;font-weight:500;--tw-text-opacity:1;color:rgb(var(--accent-950)/var(--tw-text-opacity,1))}#search-results mark:is(.dark *){background-color:rgb(var(--accent-600)/.5);--tw-text-opacity:1;color:rgb(var(--accent-100)/var(--tw-text-opacity,1))}::highlight(doc-search){background-color:rgb(var(--accent-300));color:rgb(var(--accent-950))}.dark ::highlight(doc-search){background-color:rgb(var(--accent-600));color:#fff}::highlight(doc-match){background-color:rgb(var(--accent-500));color:#fff}.dark ::highlight(doc-match){background-color:rgb(var(--accent-300));color:rgb(var(--accent-950))}.swatch{height:1.5rem;width:1.5rem;border-radius:9999px;border-width:2px;border-color:transparent;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgb(228 228 231/var(--tw-ring-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.swatch:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.swatch:is(.dark *){--tw-ring-opacity:1;--tw-ring-color:rgb(63 63 70/var(--tw-ring-opacity,1))}.swatch.active{--tw-border-opacity:1;border-color:rgb(24 24 27/var(--tw-border-opacity,1))}.swatch.active:is(.dark *){--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.swatch-violet{background-color:#8b5cf6}.swatch-blue{background-color:#3b82f6}.swatch-emerald{background-color:#10b981}.swatch-amber{background-color:#f59e0b}.swatch-rose{background-color:#f43f5e}.pick{flex:1 1 0%;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:.25rem .5rem;font-size:12px;--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.pick:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.pick:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.pick:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.pick.active{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(var(--accent-700)/var(--tw-text-opacity,1))}.pick.active:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));background-color:rgb(var(--accent-500)/.1);--tw-text-opacity:1;color:rgb(var(--accent-300)/var(--tw-text-opacity,1))}.theme-opt.theme-active{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(var(--accent-700)/var(--tw-text-opacity,1))}.theme-opt.theme-active:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1));background-color:rgb(var(--accent-500)/.1);--tw-text-opacity:1;color:rgb(var(--accent-300)/var(--tw-text-opacity,1))}.set-group{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.set-group:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.set-group>summary{display:flex;cursor:pointer;list-style-type:none;align-items:center;gap:.5rem;padding-top:.625rem;padding-bottom:.625rem;font-size:12.5px;font-weight:500;--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.set-group>summary:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.set-group>summary::-webkit-details-marker{display:none}.set-group>summary:after{content:\"›\";margin-left:auto;font-size:15px;line-height:1;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.set-group>summary:is(.dark *):after{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.set-group[open]>summary:after{transform:rotate(90deg)}.set-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:400;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.set-sub:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.set-row{display:flex;align-items:flex-start;gap:.75rem;padding-top:.375rem;padding-bottom:.375rem}.set-label{width:72px;flex-shrink:0;padding-top:.375rem;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.set-label:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}#sheet.fullscreen{max-width:none}#sheet.fullscreen #sheet-content{margin-left:auto;margin-right:auto;max-width:42rem}.task-card{position:relative;width:100%;cursor:pointer;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1));padding:.625rem .75rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.task-card:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.task-card:focus-visible{outline-style:solid;outline-width:2px;outline-offset:1px;outline-color:rgb(var(--accent-500)/1)}.task-card:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.task-card:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1))}.card-group>summary{display:flex;cursor:pointer;list-style-type:none;align-items:center;gap:.375rem;border-radius:.25rem;padding:.25rem .375rem;font-size:11px;font-weight:500;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.card-group>summary:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.card-group>summary:is(.dark *){--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-group>summary:hover:is(.dark *){background-color:rgba(39,39,42,.6)}.card-group>summary::-webkit-details-marker{display:none}.card-group>summary:before{content:\"›\";display:inline-block;width:.5rem;flex-shrink:0;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.card-group>summary:is(.dark *):before{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.card-group[open]>summary:before{transform:rotate(90deg)}.card-group-count{margin-left:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:10px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-group-count:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.card-group-body{display:flex;flex-direction:column;gap:.5rem;padding-bottom:.25rem;padding-top:.25rem}.card-group-body:empty{min-height:28px}.card-move{position:absolute;right:.25rem;top:.25rem;z-index:10;display:flex;flex-direction:column;opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.task-card:focus-within .card-move,.task-card:hover .card-move{opacity:1}.card-move>button{border-radius:.25rem;padding:.125rem;--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.card-move>button:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.card-move>button:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.card-move>button:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}@media (hover:none){.card-move{opacity:1}}.drop-marker{margin-top:-.125rem;margin-bottom:-.125rem;height:.125rem;border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(var(--accent-500)/var(--tw-bg-opacity,1))}.drop-marker:is(.dark *){--tw-bg-opacity:1;background-color:rgb(var(--accent-400)/var(--tw-bg-opacity,1))}.card-id{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-id:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.card-title{font-size:13px;font-weight:500;line-height:1.375;--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.card-title:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.card-progress{margin-left:auto;display:inline-flex;align-items:center;gap:.375rem;font-size:10px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.card-progress:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.epic-chip{border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:1px .375rem;font-size:10px;font-weight:500;--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.epic-chip:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.epic-chip:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.epic-chip:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.prio{display:inline-flex;align-items:center;gap:.25rem;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.prio:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.prio-label{font-size:10px;font-weight:500;letter-spacing:.025em}.dep-chip{display:inline-flex;align-items:center;gap:.25rem;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1));padding:1px .375rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:10px;--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dep-chip:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dep-chip:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.dep-chip:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1));--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dep-chip.done{border-color:transparent;--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity,1))}.dep-chip.done:hover{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.dep-chip.done:is(.dark *){background-color:rgba(16,185,129,.1);--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.dep-chip.done:hover:is(.dark *){background-color:rgba(16,185,129,.2)}.backlink-row{display:flex;width:100%;align-items:center;gap:.5rem;border-radius:.375rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1));padding:.375rem .625rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.backlink-row:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.backlink-row:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.backlink-row:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.epic-row{display:flex;width:100%;cursor:pointer;align-items:center;gap:.5rem;border-radius:.375rem;padding:.375rem .5rem;text-align:left;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.epic-row:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.epic-row:hover:is(.dark *){background-color:rgba(39,39,42,.7)}.epic-row.epic-active{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.epic-row.epic-active:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}#sidebar>*{flex-shrink:0}#sidebar.collapsed,#sidebar.collapsed+.sidebar-resizer{display:none!important}section.drop-target{background-color:rgb(var(--accent-50)/.6);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-inset:inset;--tw-ring-opacity:1;--tw-ring-color:rgb(var(--accent-300)/var(--tw-ring-opacity,1))}section.drop-target:is(.dark *){background-color:rgb(var(--accent-500)/.05);--tw-ring-color:rgb(var(--accent-500)/0.4)}.task-card.\\!dragging,.task-card.dragging{opacity:.4}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-top-0\\.5{top:-.125rem}.bottom-3{bottom:.75rem}.bottom-5{bottom:1.25rem}.left-1{left:.25rem}.left-1\\/2{left:50%}.left-3{left:.75rem}.left-44{left:11rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.top-0{top:0}.top-4{top:1rem}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.z-\\[60\\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.-ml-0\\.5{margin-left:-.125rem}.mb-1{margin-bottom:.25rem}.mb-1\\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-2\\.5{margin-bottom:.625rem}.mb-3{margin-bottom:.75rem}.mb-8{margin-bottom:2rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1\\.5{margin-right:.375rem}.mr-16{margin-right:4rem}.mt-1{margin-top:.25rem}.mt-1\\.5{margin-top:.375rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\\.5{height:.375rem}.h-12{height:3rem}.h-2{height:.5rem}.h-3\\.5{height:.875rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-\\[calc\\(\\(100vh\\/var\\(--zoom\\)\\)-3rem\\)\\]{height:calc(100vh/var(--zoom) - 3rem)}.h-\\[calc\\(100vh\\/var\\(--zoom\\)\\)\\]{height:calc(100vh/var(--zoom))}.h-full{height:100%}.min-h-\\[60px\\]{min-height:60px}.w-1{width:.25rem}.w-1\\.5{width:.375rem}.w-2{width:.5rem}.w-3\\.5{width:.875rem}.w-44{width:11rem}.w-56{width:14rem}.w-60{width:15rem}.w-\\[290px\\]{width:290px}.w-full{width:100%}.min-w-0{min-width:0}.max-w-3xl{max-width:48rem}.max-w-\\[460px\\]{max-width:460px}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\\/2{--tw-translate-x:-50%}.-translate-x-1\\/2,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-col-resize{cursor:col-resize}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\\[90px_1fr\\]{grid-template-columns:90px 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-y-1\\.5{row-gap:.375rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-zinc-200>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(228 228 231/var(--tw-divide-opacity,1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.border-y{border-top-width:1px}.border-b,.border-y{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-rose-300{--tw-border-opacity:1;border-color:rgb(253 164 175/var(--tw-border-opacity,1))}.border-rose-500\\/70{border-color:rgba(244,63,94,.7)}.border-zinc-100{--tw-border-opacity:1;border-color:rgb(244 244 245/var(--tw-border-opacity,1))}.border-zinc-200{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.bg-accent-50{--tw-bg-opacity:1;background-color:rgb(var(--accent-50)/var(--tw-bg-opacity,1))}.bg-accent-600{--tw-bg-opacity:1;background-color:rgb(var(--accent-600)/var(--tw-bg-opacity,1))}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-black\\/20{background-color:rgba(0,0,0,.2)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-rose-50{--tw-bg-opacity:1;background-color:rgb(255 241 242/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))}.bg-zinc-100{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.bg-zinc-300{--tw-bg-opacity:1;background-color:rgb(212 212 216/var(--tw-bg-opacity,1))}.bg-zinc-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.bg-zinc-900{--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.p-0\\.5{padding:.125rem}.p-1{padding:.25rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-96{padding:24rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\\.5{padding-left:.375rem;padding-right:.375rem}.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-8{padding-left:2rem;padding-right:2rem}.py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\\.5{padding-top:.875rem;padding-bottom:.875rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-px{padding-top:1px;padding-bottom:1px}.pb-1{padding-bottom:.25rem}.pb-3{padding-bottom:.75rem}.pl-2\\.5{padding-left:.625rem}.pr-1{padding-right:.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:var(--font-ui)}.font-serif{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.text-\\[10\\.5px\\]{font-size:10.5px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[12\\.5px\\]{font-size:12.5px}.text-\\[12px\\]{font-size:12px}.text-\\[13px\\]{font-size:13px}.text-\\[16px\\]{font-size:16px}.text-\\[9\\.5px\\]{font-size:9.5px}.text-\\[9px\\]{font-size:9px}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.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)}.leading-5{line-height:1.25rem}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-accent-600{--tw-text-opacity:1;color:rgb(var(--accent-600)/var(--tw-text-opacity,1))}.text-amber-600{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-rose-500{--tw-text-opacity:1;color:rgb(244 63 94/var(--tw-text-opacity,1))}.text-rose-700{--tw-text-opacity:1;color:rgb(190 18 60/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-zinc-100{--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.text-zinc-700{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.text-zinc-800{--tw-text-opacity:1;color:rgb(39 39 42/var(--tw-text-opacity,1))}.text-zinc-900{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-accent-600{accent-color:rgb(var(--accent-600)/1)}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;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-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}:root,html[data-accent=violet]{--accent-50:245 243 255;--accent-100:237 233 254;--accent-200:221 214 254;--accent-300:196 181 253;--accent-400:167 139 250;--accent-500:139 92 246;--accent-600:124 58 237;--accent-700:109 40 217;--accent-950:46 16 101}html[data-accent=blue]{--accent-50:239 246 255;--accent-100:219 234 254;--accent-200:191 219 254;--accent-300:147 197 253;--accent-400:96 165 250;--accent-500:59 130 246;--accent-600:37 99 235;--accent-700:29 78 216;--accent-950:23 37 84}html[data-accent=emerald]{--accent-50:236 253 245;--accent-100:209 250 229;--accent-200:167 243 208;--accent-300:110 231 183;--accent-400:52 211 153;--accent-500:16 185 129;--accent-600:5 150 105;--accent-700:4 120 87;--accent-950:2 44 34}html[data-accent=amber]{--accent-50:255 251 235;--accent-100:254 243 199;--accent-200:253 230 138;--accent-300:252 211 77;--accent-400:251 191 36;--accent-500:245 158 11;--accent-600:217 119 6;--accent-700:180 83 9;--accent-950:69 26 3}html[data-accent=rose]{--accent-50:255 241 242;--accent-100:255 228 230;--accent-200:254 205 211;--accent-300:253 164 175;--accent-400:251 113 133;--accent-500:244 63 94;--accent-600:225 29 72;--accent-700:190 18 60;--accent-950:76 5 25}:root,html[data-font=sans]{--font-ui:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif}html[data-font=serif]{--font-ui:ui-serif,Georgia,Cambria,\"Times New Roman\",Times,serif}html[data-font=mono]{--font-ui:ui-monospace,SFMono-Regular,\"SF Mono\",Menlo,Consolas,\"Liberation Mono\",monospace}:root{--zoom:1}html[data-size=compact]{--zoom:0.9}html[data-size=large]{--zoom:1.15}html[data-size=compact] body,html[data-size=large] body{zoom:var(--zoom)}@media (prefers-reduced-motion:no-preference){html.theme-anim,html.theme-anim *,html.theme-anim :after,html.theme-anim :before{transition:background-color .26s cubic-bezier(.4,0,.2,1),border-color .26s cubic-bezier(.4,0,.2,1),color .26s cubic-bezier(.4,0,.2,1),fill .26s cubic-bezier(.4,0,.2,1),stroke .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1)!important;transition-delay:0s!important}}.placeholder\\:text-zinc-400::-moz-placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.placeholder\\:text-zinc-400::placeholder{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.hover\\:border-zinc-300:hover{--tw-border-opacity:1;border-color:rgb(212 212 216/var(--tw-border-opacity,1))}.hover\\:bg-accent-400\\/70:hover{background-color:rgb(var(--accent-400)/.7)}.hover\\:bg-accent-500:hover{--tw-bg-opacity:1;background-color:rgb(var(--accent-500)/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-100:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-200:hover{--tw-bg-opacity:1;background-color:rgb(228 228 231/var(--tw-bg-opacity,1))}.hover\\:bg-zinc-50:hover{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.hover\\:text-zinc-600:hover{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.hover\\:text-zinc-900:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.hover\\:underline:hover{text-decoration-line:underline}.focus\\:border-accent-400:focus{--tw-border-opacity:1;border-color:rgb(var(--accent-400)/var(--tw-border-opacity,1))}.focus\\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:opacity-100:focus-visible{opacity:1}.active\\:bg-accent-400\\/70:active{background-color:rgb(var(--accent-400)/.7)}.group:hover .group-hover\\:opacity-100{opacity:1}@media (prefers-reduced-motion:no-preference){.motion-safe\\:transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.motion-safe\\:duration-200{transition-duration:.2s}}.dark\\:divide-zinc-800:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(39 39 42/var(--tw-divide-opacity,1))}.dark\\:border-rose-500\\/40:is(.dark *){border-color:rgba(244,63,94,.4)}.dark\\:border-zinc-700:is(.dark *){--tw-border-opacity:1;border-color:rgb(63 63 70/var(--tw-border-opacity,1))}.dark\\:border-zinc-800:is(.dark *){--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.dark\\:bg-accent-500\\/10:is(.dark *){background-color:rgb(var(--accent-500)/.1)}.dark\\:bg-amber-500\\/10:is(.dark *){background-color:rgba(245,158,11,.1)}.dark\\:bg-black\\/50:is(.dark *){background-color:rgba(0,0,0,.5)}.dark\\:bg-rose-500\\/10:is(.dark *){background-color:rgba(244,63,94,.1)}.dark\\:bg-zinc-100:is(.dark *){--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.dark\\:bg-zinc-950:is(.dark *){--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.dark\\:text-accent-400:is(.dark *){--tw-text-opacity:1;color:rgb(var(--accent-400)/var(--tw-text-opacity,1))}.dark\\:text-amber-400:is(.dark *){--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.dark\\:text-rose-300:is(.dark *){--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.dark\\:text-zinc-100:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.dark\\:text-zinc-200:is(.dark *){--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.dark\\:text-zinc-300:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dark\\:text-zinc-400:is(.dark *){--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.dark\\:text-zinc-50:is(.dark *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity,1))}.dark\\:text-zinc-500:is(.dark *){--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.dark\\:text-zinc-600:is(.dark *){--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:text-zinc-700:is(.dark *){--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.dark\\:text-zinc-900:is(.dark *){--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.dark\\:brightness-125:is(.dark *){--tw-brightness:brightness(1.25);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)}.dark\\:placeholder\\:text-zinc-600:is(.dark *)::-moz-placeholder{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:placeholder\\:text-zinc-600:is(.dark *)::placeholder{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.dark\\:hover\\:border-zinc-600:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(82 82 91/var(--tw-border-opacity,1))}.dark\\:hover\\:bg-accent-500\\/60:hover:is(.dark *){background-color:rgb(var(--accent-500)/.6)}.dark\\:hover\\:bg-zinc-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(63 63 70/var(--tw-bg-opacity,1))}.dark\\:hover\\:bg-zinc-800:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(39 39 42/var(--tw-bg-opacity,1))}.dark\\:hover\\:bg-zinc-900:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}.dark\\:hover\\:text-zinc-100:hover:is(.dark *){--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.dark\\:hover\\:text-zinc-300:hover:is(.dark *){--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.dark\\:focus\\:border-accent-500:focus:is(.dark *){--tw-border-opacity:1;border-color:rgb(var(--accent-500)/var(--tw-border-opacity,1))}.dark\\:active\\:bg-accent-500\\/60:active:is(.dark *){background-color:rgb(var(--accent-500)/.6)}@media (min-width:640px){.sm\\:block{display:block}}@media (min-width:768px){.md\\:block{display:block}.md\\:flex{display:flex}}@media (min-width:1024px){.lg\\:block{display:block}}.dark\\:\\[\\&\\>option\\]\\:bg-zinc-900>option:is(.dark *){--tw-bg-opacity:1;background-color:rgb(24 24 27/var(--tw-bg-opacity,1))}";
46
46
 
47
47
  // assets/logo.svg
48
48
  var logo_default = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="120 12 800 800">
@@ -515,11 +515,44 @@ var board_default = `(() => {
515
515
  const el = document.activeElement;
516
516
  return e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey && !/INPUT|TEXTAREA|SELECT/.test(el?.tagName ?? "") && !el?.isContentEditable;
517
517
  }
518
+ function initCopyCode() {
519
+ document.addEventListener("click", (e) => {
520
+ const btn = e.target.closest(".copy-code");
521
+ const pre = btn?.previousElementSibling;
522
+ if (!btn || !(pre instanceof HTMLElement))
523
+ return;
524
+ copyText(pre.innerText).then((ok) => {
525
+ showToast(ok ? "Copied" : "Copy failed");
526
+ if (!ok)
527
+ return;
528
+ btn.classList.add("copied");
529
+ setTimeout(() => btn.classList.remove("copied"), 1200);
530
+ });
531
+ });
532
+ }
533
+ async function copyText(text) {
534
+ try {
535
+ if (navigator.clipboard) {
536
+ await navigator.clipboard.writeText(text);
537
+ return true;
538
+ }
539
+ } catch {}
540
+ const ta = document.createElement("textarea");
541
+ ta.value = text;
542
+ ta.setAttribute("readonly", "");
543
+ ta.className = "fixed opacity-0";
544
+ document.body.append(ta);
545
+ ta.select();
546
+ const ok = document.execCommand("copy");
547
+ ta.remove();
548
+ return ok;
549
+ }
518
550
  function initChrome() {
519
551
  initResizer();
520
552
  initTheme();
521
553
  initSheet();
522
554
  initCheckboxes();
555
+ initCopyCode();
523
556
  }
524
557
 
525
558
  // src/client/board.ts
@@ -540,6 +573,11 @@ var board_default = `(() => {
540
573
  for (const r of document.querySelectorAll("[data-filter-epic]")) {
541
574
  r.classList.toggle("epic-active", (r.dataset.filterEpic || null) === epic);
542
575
  }
576
+ for (const g of document.querySelectorAll(".card-group")) {
577
+ const shown = g.querySelectorAll(".task-card:not(.hidden)").length;
578
+ g.classList.toggle("hidden", shown === 0);
579
+ g.querySelector(".card-group-count").textContent = String(shown);
580
+ }
543
581
  for (const s of document.querySelectorAll("section[data-col]")) {
544
582
  s.querySelector(".col-count").textContent = String(s.querySelectorAll(".task-card:not(.hidden)").length);
545
583
  }
@@ -584,6 +622,7 @@ var board_default = `(() => {
584
622
  document.getElementById("app").innerHTML = doc.getElementById("app").innerHTML;
585
623
  document.getElementById("header-meta").innerHTML = doc.getElementById("header-meta").innerHTML;
586
624
  applySidebarState();
625
+ applyGroupFolds();
587
626
  applyFilter(activeEpic);
588
627
  clearPaneCache();
589
628
  if (sheetIsOpen() && location.hash.length > 1) {
@@ -604,6 +643,8 @@ var board_default = `(() => {
604
643
  return;
605
644
  if (target.closest("[data-open]"))
606
645
  return;
646
+ if (target.closest("[data-move]"))
647
+ return;
607
648
  const row = target.closest("[data-filter-epic]");
608
649
  if (row) {
609
650
  applyFilter(row.dataset.filterEpic === activeEpic ? null : row.dataset.filterEpic || null);
@@ -633,17 +674,73 @@ var board_default = `(() => {
633
674
  return;
634
675
  }
635
676
  const target = e.target;
677
+ if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
678
+ const card = target.closest(".task-card");
679
+ if (card) {
680
+ e.preventDefault();
681
+ moveCard(card, e.key === "ArrowUp" ? "up" : "down");
682
+ return;
683
+ }
684
+ }
636
685
  if ((e.key === "Enter" || e.key === " ") && target instanceof HTMLElement && target.getAttribute("role") === "button") {
637
686
  e.preventDefault();
638
687
  target.click();
639
688
  }
640
689
  });
690
+ var groupsCollapsedKey = "boardCollapsedGroups";
691
+ function collapsedGroups() {
692
+ try {
693
+ return new Set(JSON.parse(localStorage.getItem(groupsCollapsedKey) || "[]"));
694
+ } catch {
695
+ return new Set;
696
+ }
697
+ }
698
+ function applyGroupFolds() {
699
+ const shut = collapsedGroups();
700
+ for (const d of document.querySelectorAll(".card-group"))
701
+ d.open = !shut.has(d.dataset.group);
702
+ }
703
+ document.addEventListener("toggle", (e) => {
704
+ const d = e.target.closest(".card-group");
705
+ if (!d)
706
+ return;
707
+ const shut = collapsedGroups();
708
+ if (d.open)
709
+ shut.delete(d.dataset.group);
710
+ else
711
+ shut.add(d.dataset.group);
712
+ localStorage.setItem(groupsCollapsedKey, JSON.stringify([...shut]));
713
+ }, true);
714
+ function visibleSiblings(card) {
715
+ const body = card.closest(".card-group-body");
716
+ return body ? [...body.querySelectorAll(".task-card:not(.hidden)")] : [card];
717
+ }
718
+ function moveCard(card, dir) {
719
+ const sibs = visibleSiblings(card);
720
+ const at = sibs.indexOf(card);
721
+ if (at === -1 || dir === "up" && at === 0 || dir === "down" && at === sibs.length - 1)
722
+ return;
723
+ const target = sibs[dir === "up" ? at - 1 : at + 1];
724
+ target.insertAdjacentElement(dir === "up" ? "beforebegin" : "afterend", card);
725
+ card.focus();
726
+ patchItem(card.dataset.taskId, { move: dir }, card.dataset.rev);
727
+ }
728
+ document.addEventListener("click", (e) => {
729
+ const btn = e.target.closest?.("[data-move]");
730
+ if (!btn)
731
+ return;
732
+ moveCard(btn.closest(".task-card"), btn.dataset.move);
733
+ });
641
734
  var dragId = null;
642
735
  var dragRev = null;
643
736
  var dragStatus = null;
737
+ var dragEpic = null;
738
+ var marker = document.createElement("div");
739
+ marker.className = "drop-marker";
644
740
  function clearDropTargets() {
645
741
  for (const s of document.querySelectorAll("section.drop-target"))
646
742
  s.classList.remove("drop-target");
743
+ marker.remove();
647
744
  }
648
745
  document.addEventListener("dragstart", (e) => {
649
746
  const card = e.target.closest?.("[data-task-id]");
@@ -652,6 +749,7 @@ var board_default = `(() => {
652
749
  dragId = card.dataset.taskId;
653
750
  dragRev = card.dataset.rev;
654
751
  dragStatus = card.dataset.status;
752
+ dragEpic = card.dataset.epic;
655
753
  e.dataTransfer.effectAllowed = "move";
656
754
  card.classList.add("dragging");
657
755
  });
@@ -660,23 +758,54 @@ var board_default = `(() => {
660
758
  clearDropTargets();
661
759
  dragId = null;
662
760
  });
761
+ function dropAnchor(body, y) {
762
+ const cards = [...body.querySelectorAll(".task-card:not(.dragging):not(.hidden)")];
763
+ for (const c of cards) {
764
+ const box = c.getBoundingClientRect();
765
+ if (y < box.top + box.height / 2)
766
+ return { id: c.dataset.taskId, where: "before" };
767
+ }
768
+ const last = cards[cards.length - 1];
769
+ return last ? { id: last.dataset.taskId, where: "after" } : null;
770
+ }
663
771
  document.addEventListener("dragover", (e) => {
772
+ if (!dragId)
773
+ return;
664
774
  const col = e.target.closest?.("section[data-col]");
665
- if (col && dragId) {
666
- e.preventDefault();
667
- e.dataTransfer.dropEffect = "move";
668
- if (!col.classList.contains("drop-target")) {
669
- clearDropTargets();
670
- col.classList.add("drop-target");
671
- }
775
+ if (!col)
776
+ return;
777
+ e.preventDefault();
778
+ e.dataTransfer.dropEffect = "move";
779
+ if (!col.classList.contains("drop-target")) {
780
+ clearDropTargets();
781
+ col.classList.add("drop-target");
672
782
  }
783
+ const body = e.target.closest?.(".card-group-body");
784
+ if (!body)
785
+ return marker.remove();
786
+ const anchor = dropAnchor(body, e.clientY);
787
+ if (!anchor)
788
+ return body.append(marker);
789
+ const el = body.querySelector(\`[data-task-id="\${anchor.id}"]\`);
790
+ el.insertAdjacentElement(anchor.where === "before" ? "beforebegin" : "afterend", marker);
673
791
  });
674
792
  document.addEventListener("drop", (e) => {
675
793
  const col = e.target.closest?.("section[data-col]");
676
794
  if (col && dragId) {
677
795
  e.preventDefault();
796
+ const body = e.target.closest?.(".card-group-body");
797
+ const patch = {};
678
798
  if (col.dataset.col !== dragStatus)
679
- patchItem(dragId, { status: col.dataset.col }, dragRev);
799
+ patch.status = col.dataset.col;
800
+ if (body && body.dataset.dropEpic !== dragEpic)
801
+ patch.epic = body.dataset.dropEpic;
802
+ if (body) {
803
+ const anchor = dropAnchor(body, e.clientY);
804
+ if (anchor && anchor.id !== dragId)
805
+ patch[anchor.where] = anchor.id;
806
+ }
807
+ if (Object.keys(patch).length)
808
+ patchItem(dragId, patch, dragRev);
680
809
  }
681
810
  clearDropTargets();
682
811
  dragId = null;
@@ -687,6 +816,7 @@ var board_default = `(() => {
687
816
  });
688
817
  connectLive(() => void refreshApp(), 120);
689
818
  applySidebarState();
819
+ applyGroupFolds();
690
820
  if (location.hash.length > 1)
691
821
  openSheet(location.hash.slice(1));
692
822
  })();
@@ -1100,11 +1230,44 @@ var docs_default = `(() => {
1100
1230
  const el = document.activeElement;
1101
1231
  return e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey && !/INPUT|TEXTAREA|SELECT/.test(el?.tagName ?? "") && !el?.isContentEditable;
1102
1232
  }
1233
+ function initCopyCode() {
1234
+ document.addEventListener("click", (e) => {
1235
+ const btn = e.target.closest(".copy-code");
1236
+ const pre = btn?.previousElementSibling;
1237
+ if (!btn || !(pre instanceof HTMLElement))
1238
+ return;
1239
+ copyText(pre.innerText).then((ok) => {
1240
+ showToast(ok ? "Copied" : "Copy failed");
1241
+ if (!ok)
1242
+ return;
1243
+ btn.classList.add("copied");
1244
+ setTimeout(() => btn.classList.remove("copied"), 1200);
1245
+ });
1246
+ });
1247
+ }
1248
+ async function copyText(text) {
1249
+ try {
1250
+ if (navigator.clipboard) {
1251
+ await navigator.clipboard.writeText(text);
1252
+ return true;
1253
+ }
1254
+ } catch {}
1255
+ const ta = document.createElement("textarea");
1256
+ ta.value = text;
1257
+ ta.setAttribute("readonly", "");
1258
+ ta.className = "fixed opacity-0";
1259
+ document.body.append(ta);
1260
+ ta.select();
1261
+ const ok = document.execCommand("copy");
1262
+ ta.remove();
1263
+ return ok;
1264
+ }
1103
1265
  function initChrome() {
1104
1266
  initResizer();
1105
1267
  initTheme();
1106
1268
  initSheet();
1107
1269
  initCheckboxes();
1270
+ initCopyCode();
1108
1271
  }
1109
1272
 
1110
1273
  // src/client/docs.ts
@@ -1935,11 +2098,44 @@ var graph_default = `(() => {
1935
2098
  const el = document.activeElement;
1936
2099
  return e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey && !/INPUT|TEXTAREA|SELECT/.test(el?.tagName ?? "") && !el?.isContentEditable;
1937
2100
  }
2101
+ function initCopyCode() {
2102
+ document.addEventListener("click", (e) => {
2103
+ const btn = e.target.closest(".copy-code");
2104
+ const pre = btn?.previousElementSibling;
2105
+ if (!btn || !(pre instanceof HTMLElement))
2106
+ return;
2107
+ copyText(pre.innerText).then((ok) => {
2108
+ showToast(ok ? "Copied" : "Copy failed");
2109
+ if (!ok)
2110
+ return;
2111
+ btn.classList.add("copied");
2112
+ setTimeout(() => btn.classList.remove("copied"), 1200);
2113
+ });
2114
+ });
2115
+ }
2116
+ async function copyText(text) {
2117
+ try {
2118
+ if (navigator.clipboard) {
2119
+ await navigator.clipboard.writeText(text);
2120
+ return true;
2121
+ }
2122
+ } catch {}
2123
+ const ta = document.createElement("textarea");
2124
+ ta.value = text;
2125
+ ta.setAttribute("readonly", "");
2126
+ ta.className = "fixed opacity-0";
2127
+ document.body.append(ta);
2128
+ ta.select();
2129
+ const ok = document.execCommand("copy");
2130
+ ta.remove();
2131
+ return ok;
2132
+ }
1938
2133
  function initChrome() {
1939
2134
  initResizer();
1940
2135
  initTheme();
1941
2136
  initSheet();
1942
2137
  initCheckboxes();
2138
+ initCopyCode();
1943
2139
  }
1944
2140
 
1945
2141
  // src/client/graph.ts
@@ -2582,6 +2778,7 @@ function parseTask(file) {
2582
2778
  epic: fm.epic ?? "",
2583
2779
  status: fm.status ?? "backlog",
2584
2780
  priority: fm.priority ?? "P3",
2781
+ order: fm.order !== undefined && fm.order.trim() !== "" && Number.isFinite(Number(fm.order)) ? Number(fm.order) : null,
2585
2782
  depends_on: parseInlineList(fm.depends_on ?? ""),
2586
2783
  created: fm.created ?? "",
2587
2784
  body,
@@ -2657,6 +2854,8 @@ function setFrontmatterValue(raw, key, value) {
2657
2854
  function getFrontmatterValue(raw, key) {
2658
2855
  return parseFrontmatter(raw)?.fm[key] ?? "";
2659
2856
  }
2857
+ var FENCE = /^([ \t]*)```/;
2858
+ var COPY_BUTTON = `<button type="button" class="copy-code" aria-label="Copy code" title="Copy">` + `<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true">` + `<rect x="5.5" y="5.5" width="8" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/>` + `<path d="M10.5 3.5 A1.5 1.5 0 0 0 9 2.5 H4 A1.5 1.5 0 0 0 2.5 4 v5 a1.5 1.5 0 0 0 1 1.4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>` + `</svg></button>`;
2660
2859
  function toggleCheckboxLine(raw, index, checked) {
2661
2860
  const m = raw.match(/^(---\n[\s\S]*?\n---\n?)([\s\S]*)$/);
2662
2861
  const head = m ? m[1] : "";
@@ -2665,7 +2864,7 @@ function toggleCheckboxLine(raw, index, checked) {
2665
2864
  let inCode = false;
2666
2865
  let count = 0;
2667
2866
  for (let i = 0;i < lines.length; i++) {
2668
- if (lines[i].startsWith("```")) {
2867
+ if (FENCE.test(lines[i])) {
2669
2868
  inCode = !inCode;
2670
2869
  continue;
2671
2870
  }
@@ -2760,6 +2959,7 @@ function mdToHtml(md, opts = {}) {
2760
2959
  const out = [];
2761
2960
  let inCode = false;
2762
2961
  let codeLang = "";
2962
+ let codeIndent = 0;
2763
2963
  let inList = false;
2764
2964
  let cbIndex = 0;
2765
2965
  let tableBuf = [];
@@ -2785,21 +2985,23 @@ function mdToHtml(md, opts = {}) {
2785
2985
  }
2786
2986
  };
2787
2987
  for (const line of lines) {
2788
- if (line.startsWith("```")) {
2988
+ const fence = line.match(FENCE);
2989
+ if (fence) {
2789
2990
  flushTable();
2790
2991
  closeList();
2791
2992
  if (!inCode) {
2792
- codeLang = line.slice(3).trim();
2993
+ codeIndent = fence[1].length;
2994
+ codeLang = line.slice(fence[0].length).trim();
2793
2995
  inCode = true;
2794
- out.push(opts.docMode && codeLang === "mermaid" ? '<div class="mermaid">' : "<pre>");
2996
+ out.push(opts.docMode && codeLang === "mermaid" ? '<div class="mermaid">' : `<div class="codeblock"><pre>`);
2795
2997
  } else {
2796
- out.push(opts.docMode && codeLang === "mermaid" ? "</div>" : "</pre>");
2998
+ out.push(opts.docMode && codeLang === "mermaid" ? "</div>" : `</pre>${COPY_BUTTON}</div>`);
2797
2999
  inCode = false;
2798
3000
  }
2799
3001
  continue;
2800
3002
  }
2801
3003
  if (inCode) {
2802
- out.push(line);
3004
+ out.push(line.slice(0, codeIndent).trim() ? line : line.slice(codeIndent));
2803
3005
  continue;
2804
3006
  }
2805
3007
  if (/^\s*\|/.test(line)) {
@@ -2853,7 +3055,7 @@ function mdToHtml(md, opts = {}) {
2853
3055
  flushTable();
2854
3056
  closeList();
2855
3057
  if (inCode)
2856
- out.push("</pre>");
3058
+ out.push(`</pre>${COPY_BUTTON}</div>`);
2857
3059
  return out.join(`
2858
3060
  `);
2859
3061
  }
@@ -2915,32 +3117,30 @@ function normalizeRel(baseDir, href) {
2915
3117
  }
2916
3118
  var buildBacklinks = memoByVersion(() => {
2917
3119
  const map = new Map;
2918
- for (const g of listDocs()) {
2919
- for (const rel of g.files) {
2920
- const parsed = parseCached("fm", join(PLANNER_DIR, ...rel.split("/")), (raw) => parseFrontmatter(raw) ?? { fm: {}, body: raw });
2921
- if (!parsed)
2922
- continue;
2923
- const { fm, body } = parsed;
2924
- const deps = new Set(parseInlineList(fm.depends_on ?? ""));
2925
- const targets = new Set;
2926
- for (const m of body.matchAll(/\b(ST-\d{3}|E\d{2})\b/g))
2927
- targets.add(m[1]);
2928
- if (fm.epic)
2929
- targets.add(fm.epic);
2930
- for (const d of deps)
2931
- targets.add(d);
2932
- const baseDir = dirname(rel) === "." ? "" : dirname(rel);
2933
- for (const m of body.matchAll(/\]\(([^)\s]+\.md)\)/g)) {
2934
- if (!/^https?:/.test(m[1]))
2935
- targets.add(normalizeRel(baseDir, m[1]));
2936
- }
2937
- targets.delete(fm.id ?? "");
2938
- targets.delete(rel);
2939
- for (const t of targets) {
2940
- const arr = map.get(t) ?? [];
2941
- arr.push({ file: rel, id: fm.id, title: fm.title ?? basename(rel), isDep: deps.has(t) });
2942
- map.set(t, arr);
2943
- }
3120
+ for (const rel of allDocFiles()) {
3121
+ const parsed = parseCached("fm", join(PLANNER_DIR, ...rel.split("/")), (raw) => parseFrontmatter(raw) ?? { fm: {}, body: raw });
3122
+ if (!parsed)
3123
+ continue;
3124
+ const { fm, body } = parsed;
3125
+ const deps = new Set(parseInlineList(fm.depends_on ?? ""));
3126
+ const targets = new Set;
3127
+ for (const m of body.matchAll(/\b(ST-\d{3}|E\d{2})\b/g))
3128
+ targets.add(m[1]);
3129
+ if (fm.epic)
3130
+ targets.add(fm.epic);
3131
+ for (const d of deps)
3132
+ targets.add(d);
3133
+ const baseDir = dirname(rel) === "." ? "" : dirname(rel);
3134
+ for (const m of body.matchAll(/\]\(([^)\s]+\.md)\)/g)) {
3135
+ if (!/^https?:/.test(m[1]))
3136
+ targets.add(normalizeRel(baseDir, m[1]));
3137
+ }
3138
+ targets.delete(fm.id ?? "");
3139
+ targets.delete(rel);
3140
+ for (const t of targets) {
3141
+ const arr = map.get(t) ?? [];
3142
+ arr.push({ file: rel, id: fm.id, title: fm.title ?? basename(rel), isDep: deps.has(t) });
3143
+ map.set(t, arr);
2944
3144
  }
2945
3145
  }
2946
3146
  return map;
@@ -2948,14 +3148,12 @@ var buildBacklinks = memoByVersion(() => {
2948
3148
  var buildGraph = memoByVersion(() => {
2949
3149
  const nodes = new Map;
2950
3150
  const byItemId = new Map;
2951
- for (const g of listDocs()) {
2952
- for (const rel of g.files) {
2953
- const parsed = parseCached("fm", join(PLANNER_DIR, ...rel.split("/")), (raw) => parseFrontmatter(raw) ?? { fm: {}, body: raw });
2954
- const fm = parsed?.fm ?? {};
2955
- nodes.set(rel, { id: rel, label: fm.title || basename(rel).replace(/\.md$/i, ""), group: g.group, deg: 0 });
2956
- if (fm.id)
2957
- byItemId.set(fm.id, rel);
2958
- }
3151
+ for (const rel of allDocFiles()) {
3152
+ const parsed = parseCached("fm", join(PLANNER_DIR, ...rel.split("/")), (raw) => parseFrontmatter(raw) ?? { fm: {}, body: raw });
3153
+ const fm = parsed?.fm ?? {};
3154
+ nodes.set(rel, { id: rel, label: fm.title || basename(rel).replace(/\.md$/i, ""), group: docGroup(rel), deg: 0 });
3155
+ if (fm.id)
3156
+ byItemId.set(fm.id, rel);
2959
3157
  }
2960
3158
  const links = [];
2961
3159
  const seen = new Set;
@@ -2991,73 +3189,81 @@ function backlinksHtml(sources, heading, docMode) {
2991
3189
  return `<a href="${href}" class="${rowClass}">${inner}</a>`;
2992
3190
  }).join("");
2993
3191
  return `<div class="mt-6 border-t border-zinc-100 pt-4 dark:border-zinc-800">
2994
- <div class="mb-2 text-[11px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">${heading} <span class="font-mono text-[10px] normal-case text-zinc-300 dark:text-zinc-600">${sources.length}</span></div>
2995
- <div class="space-y-1.5">${rows}</div>
3192
+ <div class="mb-2 text-[11px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">${heading} <span class="font-mono text-[10px] normal-case text-zinc-300 dark:text-zinc-600">${sources.length}</span></div>
3193
+ <div class="space-y-1.5">${rows}</div>
2996
3194
  </div>`;
2997
3195
  }
2998
3196
  function cardHtml(t, byId) {
2999
3197
  const deps = t.depends_on.map((d) => depChip(d, byId.get(d)?.status === "done")).join("");
3000
3198
  const progress = t.subtasksTotal > 0 ? `<span class="card-progress" title="${t.subtasksDone} of ${t.subtasksTotal} subtasks done">
3001
- ${progressRing(t.subtasksDone, t.subtasksTotal)}
3002
- ${t.subtasksDone}/${t.subtasksTotal}</span>` : "";
3199
+ ${progressRing(t.subtasksDone, t.subtasksTotal)}
3200
+ ${t.subtasksDone}/${t.subtasksTotal}</span>` : "";
3003
3201
  const search = esc(`${t.id} ${t.title} ${t.epic} ${t.body}`.toLowerCase().replace(/\s+/g, " ").slice(0, 2000));
3004
3202
  return `<div role="button" tabindex="0" draggable="true" data-task-id="${esc(t.id)}" data-epic="${esc(t.epic)}" data-status="${esc(t.status)}" data-rev="${t.rev}" data-search="${search}"
3005
- class="task-card">
3006
- <div class="mb-1 flex items-center justify-between gap-2">
3007
- <span class="card-id">${esc(t.id)}</span>
3008
- ${priorityIcon(t.priority)}
3009
- </div>
3010
- <div class="card-title">${esc(t.title)}</div>
3011
- <div class="mt-2 flex flex-wrap items-center gap-1.5">
3012
- <button type="button" data-open="${esc(t.epic)}" class="epic-chip" title="open epic ${esc(t.epic)}">${esc(t.epic)}</button>
3013
- ${deps}${progress}
3014
- </div>
3203
+ class="task-card">
3204
+ <div class="card-move">
3205
+ <button type="button" data-move="up" tabindex="-1" aria-label="Move ${esc(t.id)} up" title="Move up (Alt+↑)">
3206
+ <svg width="11" height="11" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 10 8 6 12 10" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
3207
+ </button>
3208
+ <button type="button" data-move="down" tabindex="-1" aria-label="Move ${esc(t.id)} down" title="Move down (Alt+↓)">
3209
+ <svg width="11" height="11" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6 8 10 12 6" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
3210
+ </button>
3211
+ </div>
3212
+ <div class="mb-1 flex items-center justify-between gap-2">
3213
+ <span class="card-id">${esc(t.id)}</span>
3214
+ ${priorityIcon(t.priority)}
3215
+ </div>
3216
+ <div class="card-title">${esc(t.title)}</div>
3217
+ <div class="mt-2 flex flex-wrap items-center gap-1.5">
3218
+ <button type="button" data-open="${esc(t.epic)}" class="epic-chip" title="open epic ${esc(t.epic)}">${esc(t.epic)}</button>
3219
+ ${deps}${progress}
3220
+ </div>
3015
3221
  </div>`;
3016
3222
  }
3017
3223
  function statusSelect(current) {
3018
3224
  const options = [...new Set([...settings.columns, current])].map((s) => `<option value="${esc(s)}" ${s === current ? "selected" : ""}>${esc(s.replace("-", " "))}</option>`).join("");
3019
3225
  return `<select data-status-select aria-label="Status"
3020
- class="cursor-pointer rounded border border-zinc-200 bg-transparent px-1 py-0.5 text-[12px] capitalize text-zinc-600 hover:border-zinc-300 focus:outline-none dark:border-zinc-700 dark:text-zinc-300 dark:hover:border-zinc-600 dark:[&>option]:bg-zinc-900">${options}</select>`;
3226
+ class="cursor-pointer rounded border border-zinc-200 bg-transparent px-1 py-0.5 text-[12px] capitalize text-zinc-600 hover:border-zinc-300 focus:outline-none dark:border-zinc-700 dark:text-zinc-300 dark:hover:border-zinc-600 dark:[&>option]:bg-zinc-900">${options}</select>`;
3021
3227
  }
3022
3228
  function taskDetailHtml(t, byId, backlinks) {
3023
3229
  const deps = t.depends_on.length ? t.depends_on.map((d) => depChip(d, byId.get(d)?.status === "done")).join(" ") : '<span class="text-zinc-400 dark:text-zinc-500">none</span>';
3024
3230
  return `<div class="detail-root" data-id="${esc(t.id)}" data-rev="${t.rev}">
3025
- <div class="flex items-center gap-2 text-[12px] text-zinc-500 dark:text-zinc-400">
3026
- ${statusIcon(t.status)}${statusSelect(t.status)}
3027
- <span class="font-mono text-[11px]">${esc(t.id)}</span>
3028
- <span class="ml-auto mr-16">${priorityIcon(t.priority)}</span>
3029
- </div>
3030
- <h2 class="mt-2 text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">${esc(t.title)}</h2>
3031
- <dl class="mt-4 grid grid-cols-[90px_1fr] items-baseline gap-y-1.5 border-y border-zinc-100 py-3 text-[12px] dark:border-zinc-800">
3032
- <dt class="text-zinc-400 dark:text-zinc-500">Epic</dt><dd><button type="button" data-open="${esc(t.epic)}" class="font-mono text-accent-600 hover:underline dark:text-accent-400">${esc(t.epic)}</button></dd>
3033
- <dt class="text-zinc-400 dark:text-zinc-500">Depends on</dt><dd class="flex flex-wrap gap-1">${deps}</dd>
3034
- <dt class="text-zinc-400 dark:text-zinc-500">Created</dt><dd class="text-zinc-700 dark:text-zinc-300">${esc(t.created)}</dd>
3035
- <dt class="text-zinc-400 dark:text-zinc-500">File</dt><dd class="font-mono text-[11px] text-zinc-500 dark:text-zinc-400"><a class="hover:underline" href="/docs?file=tasks/${esc(t.file)}">tasks/${esc(t.file)}</a></dd>
3036
- </dl>
3037
- <div class="detail-body mt-4">${mdToHtml(t.body)}</div>
3038
- ${backlinksHtml(backlinks.get(t.id) ?? [], "Referenced by", false)}
3231
+ <div class="flex items-center gap-2 text-[12px] text-zinc-500 dark:text-zinc-400">
3232
+ ${statusIcon(t.status)}${statusSelect(t.status)}
3233
+ <span class="font-mono text-[11px]">${esc(t.id)}</span>
3234
+ <span class="ml-auto mr-16">${priorityIcon(t.priority)}</span>
3235
+ </div>
3236
+ <h2 class="mt-2 text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">${esc(t.title)}</h2>
3237
+ <dl class="mt-4 grid grid-cols-[90px_1fr] items-baseline gap-y-1.5 border-y border-zinc-100 py-3 text-[12px] dark:border-zinc-800">
3238
+ <dt class="text-zinc-400 dark:text-zinc-500">Epic</dt><dd><button type="button" data-open="${esc(t.epic)}" class="font-mono text-accent-600 hover:underline dark:text-accent-400">${esc(t.epic)}</button></dd>
3239
+ <dt class="text-zinc-400 dark:text-zinc-500">Depends on</dt><dd class="flex flex-wrap gap-1">${deps}</dd>
3240
+ <dt class="text-zinc-400 dark:text-zinc-500">Created</dt><dd class="text-zinc-700 dark:text-zinc-300">${esc(t.created)}</dd>
3241
+ <dt class="text-zinc-400 dark:text-zinc-500">File</dt><dd class="font-mono text-[11px] text-zinc-500 dark:text-zinc-400"><a class="hover:underline" href="/docs?file=tasks/${esc(t.file)}">tasks/${esc(t.file)}</a></dd>
3242
+ </dl>
3243
+ <div class="detail-body mt-4">${mdToHtml(t.body)}</div>
3244
+ ${backlinksHtml(backlinks.get(t.id) ?? [], "Referenced by", false)}
3039
3245
  </div>`;
3040
3246
  }
3041
3247
  function epicDetailHtml(e, tasks, backlinks) {
3042
3248
  const stories = tasks.filter((t) => t.epic === e.id);
3043
3249
  const storyList = stories.length ? stories.map((t) => `<button type="button" data-open="${esc(t.id)}" class="backlink-row">
3044
- ${statusIcon(t.status, 12)}
3045
- <span class="font-mono text-[11px] text-zinc-400 dark:text-zinc-500">${esc(t.id)}</span>
3046
- <span class="truncate text-[12.5px] text-zinc-700 dark:text-zinc-300">${esc(t.title)}</span>
3047
- </button>`).join("") : '<p class="text-[12px] text-zinc-400">No stories yet.</p>';
3250
+ ${statusIcon(t.status, 12)}
3251
+ <span class="font-mono text-[11px] text-zinc-400 dark:text-zinc-500">${esc(t.id)}</span>
3252
+ <span class="truncate text-[12.5px] text-zinc-700 dark:text-zinc-300">${esc(t.title)}</span>
3253
+ </button>`).join("") : '<p class="text-[12px] text-zinc-400">No stories yet.</p>';
3048
3254
  const done = stories.filter((t) => t.status === "done").length;
3049
3255
  return `<div class="detail-root" data-id="${esc(e.id)}" data-rev="${e.rev}">
3050
- <div class="flex items-center gap-2 text-[12px] text-zinc-500 dark:text-zinc-400">
3051
- <span class="rounded bg-zinc-100 px-1.5 py-px text-[10px] font-medium uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400">Epic</span>
3052
- <span class="font-mono text-[11px]">${esc(e.id)}</span>
3053
- <span class="text-zinc-300 dark:text-zinc-600">&middot;</span>
3054
- <span>${esc(e.milestone)}</span>
3055
- <span class="ml-auto mr-16 inline-flex items-center gap-1.5 text-zinc-400 dark:text-zinc-500">${progressRing(done, stories.length)}<span class="font-mono text-[11px]">${done}/${stories.length} done</span></span>
3056
- </div>
3057
- <h2 class="mt-2 text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">${esc(e.title)}</h2>
3058
- <div class="mt-4 space-y-1.5">${storyList}</div>
3059
- <div class="detail-body mt-5 border-t border-zinc-100 pt-4 dark:border-zinc-800">${mdToHtml(e.body)}</div>
3060
- ${backlinksHtml((backlinks.get(e.id) ?? []).filter((s) => !stories.some((t) => t.id === s.id)), "Referenced by", false)}
3256
+ <div class="flex items-center gap-2 text-[12px] text-zinc-500 dark:text-zinc-400">
3257
+ <span class="rounded bg-zinc-100 px-1.5 py-px text-[10px] font-medium uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400">Epic</span>
3258
+ <span class="font-mono text-[11px]">${esc(e.id)}</span>
3259
+ <span class="text-zinc-300 dark:text-zinc-600">&middot;</span>
3260
+ <span>${esc(e.milestone)}</span>
3261
+ <span class="ml-auto mr-16 inline-flex items-center gap-1.5 text-zinc-400 dark:text-zinc-500">${progressRing(done, stories.length)}<span class="font-mono text-[11px]">${done}/${stories.length} done</span></span>
3262
+ </div>
3263
+ <h2 class="mt-2 text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">${esc(e.title)}</h2>
3264
+ <div class="mt-4 space-y-1.5">${storyList}</div>
3265
+ <div class="detail-body mt-5 border-t border-zinc-100 pt-4 dark:border-zinc-800">${mdToHtml(e.body)}</div>
3266
+ ${backlinksHtml((backlinks.get(e.id) ?? []).filter((s) => !stories.some((t) => t.id === s.id)), "Referenced by", false)}
3061
3267
  </div>`;
3062
3268
  }
3063
3269
  function itemPaneHtml(id) {
@@ -3074,24 +3280,24 @@ function sidebarHtml(epics, tasks) {
3074
3280
  const stories = tasks.filter((t) => t.epic === e.id);
3075
3281
  const done = stories.filter((t) => t.status === "done").length;
3076
3282
  return `<div role="button" tabindex="0" data-filter-epic="${esc(e.id)}" class="epic-row group" title="${esc(e.title)}: click to filter the board">
3077
- <span class="text-zinc-400 dark:text-zinc-500">${progressRing(done, stories.length)}</span>
3078
- <span class="min-w-0 flex-1 truncate text-[12.5px] text-zinc-700 dark:text-zinc-300"><span class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-500">${esc(e.id)}</span> ${esc(e.title)}</span>
3079
- <span class="font-mono text-[10px] text-zinc-400 dark:text-zinc-600">${done}/${stories.length}</span>
3080
- <button type="button" data-open="${esc(e.id)}" aria-label="Open epic ${esc(e.id)}"
3081
- class="rounded p-0.5 text-zinc-300 opacity-0 transition-opacity hover:bg-zinc-200 hover:text-zinc-600 group-hover:opacity-100 focus-visible:opacity-100 dark:text-zinc-600 dark:hover:bg-zinc-700 dark:hover:text-zinc-300">
3082
- <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M4.5 2.5 H9.5 V7.5 M9.5 2.5 L2.5 9.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
3083
- </button>
3084
- </div>`;
3283
+ <span class="text-zinc-400 dark:text-zinc-500">${progressRing(done, stories.length)}</span>
3284
+ <span class="min-w-0 flex-1 truncate text-[12.5px] text-zinc-700 dark:text-zinc-300"><span class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-500">${esc(e.id)}</span> ${esc(e.title)}</span>
3285
+ <span class="font-mono text-[10px] text-zinc-400 dark:text-zinc-600">${done}/${stories.length}</span>
3286
+ <button type="button" data-open="${esc(e.id)}" aria-label="Open epic ${esc(e.id)}"
3287
+ class="rounded p-0.5 text-zinc-300 opacity-0 transition-opacity hover:bg-zinc-200 hover:text-zinc-600 group-hover:opacity-100 focus-visible:opacity-100 dark:text-zinc-600 dark:hover:bg-zinc-700 dark:hover:text-zinc-300">
3288
+ <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M4.5 2.5 H9.5 V7.5 M9.5 2.5 L2.5 9.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
3289
+ </button>
3290
+ </div>`;
3085
3291
  }).join("");
3086
3292
  return `<aside id="sidebar" class="hidden w-60 shrink-0 flex-col gap-0.5 overflow-y-auto border-r border-zinc-200 bg-white px-2.5 py-3 dark:border-zinc-800 dark:bg-zinc-950 md:flex">
3087
- <div class="mb-1 px-2 text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Epics</div>
3088
- <div role="button" tabindex="0" data-filter-epic=""
3089
- class="epic-row epic-active">
3090
- <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" class="text-zinc-400"><rect x="1" y="1" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="6.6" y="1" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="1" y="6.6" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="6.6" y="6.6" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/></svg>
3091
- <span class="flex-1 text-[12.5px] text-zinc-700 dark:text-zinc-300">All epics</span>
3092
- <span class="font-mono text-[10px] text-zinc-400 dark:text-zinc-600">${tasks.length}</span>
3093
- </div>
3094
- ${rows}
3293
+ <div class="mb-1 px-2 text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Epics</div>
3294
+ <div role="button" tabindex="0" data-filter-epic=""
3295
+ class="epic-row epic-active">
3296
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" class="text-zinc-400"><rect x="1" y="1" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="6.6" y="1" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="1" y="6.6" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="6.6" y="6.6" width="4.4" height="4.4" rx="1" stroke="currentColor" stroke-width="1.2"/></svg>
3297
+ <span class="flex-1 text-[12.5px] text-zinc-700 dark:text-zinc-300">All epics</span>
3298
+ <span class="font-mono text-[10px] text-zinc-400 dark:text-zinc-600">${tasks.length}</span>
3299
+ </div>
3300
+ ${rows}
3095
3301
  </aside>`;
3096
3302
  }
3097
3303
  function boardColumns(tasks) {
@@ -3103,11 +3309,11 @@ function settingsPanelHtml() {
3103
3309
  const hint = "mt-1 text-[11px] leading-relaxed text-zinc-400 dark:text-zinc-500";
3104
3310
  const row = (name, control, note = "") => `<div class="set-row"><span class="set-label">${name}</span><div class="min-w-0 flex-1">${control}${note ? `<p class="${hint}">${note}</p>` : ""}</div></div>`;
3105
3311
  const group = (title, sub, body, open = false) => `<details class="set-group" name="settings-group"${open ? " open" : ""}>
3106
- <summary>${title}<span class="set-sub">${sub}</span></summary>
3107
- <div class="pb-3">${body}</div>
3108
- </details>`;
3312
+ <summary>${title}<span class="set-sub">${sub}</span></summary>
3313
+ <div class="pb-3">${body}</div>
3314
+ </details>`;
3109
3315
  const appearance = row("Theme", `<div class="flex gap-1">${["light", "dark"].map((t) => `<button type="button" data-set-theme="${t}"
3110
- class="theme-opt pick capitalize">${t}</button>`).join("")}</div>`) + row("Accent", `<div class="flex flex-wrap gap-1.5">${[
3316
+ class="theme-opt pick capitalize">${t}</button>`).join("")}</div>`) + row("Accent", `<div class="flex flex-wrap gap-1.5">${[
3111
3317
  ["violet", "swatch swatch-violet"],
3112
3318
  ["blue", "swatch swatch-blue"],
3113
3319
  ["emerald", "swatch swatch-emerald"],
@@ -3127,48 +3333,80 @@ function settingsPanelHtml() {
3127
3333
  ["docs", "Docs", "Markdown viewer and search"],
3128
3334
  ["graph", "Graph", "Force-directed map of links"]
3129
3335
  ].map(([v, name, why]) => `
3130
- <label class="flex items-center gap-2 text-[12.5px] text-zinc-700 dark:text-zinc-300">
3131
- <input type="checkbox" name="view-${v}" class="h-3.5 w-3.5 accent-accent-600" ${settings.views.includes(v) ? "checked" : ""}>
3132
- ${name} <span class="text-[11px] text-zinc-400 dark:text-zinc-500">${why}</span>
3133
- </label>`).join("")}</div>`, "Turn off whatever this workspace does not need. At least one has to stay on.") + row("Columns", `<input id="set-columns" name="columns" class="${field}" value="${esc(settings.columns.join(", "))}">`, "Comma separated, in board order. A status used by a task always gets a column even if listed nowhere here, so nothing goes missing.");
3336
+ <label class="flex items-center gap-2 text-[12.5px] text-zinc-700 dark:text-zinc-300">
3337
+ <input type="checkbox" name="view-${v}" class="h-3.5 w-3.5 accent-accent-600" ${settings.views.includes(v) ? "checked" : ""}>
3338
+ ${name} <span class="text-[11px] text-zinc-400 dark:text-zinc-500">${why}</span>
3339
+ </label>`).join("")}</div>`, "Turn off whatever this workspace does not need. At least one has to stay on.") + row("Columns", `<input id="set-columns" name="columns" class="${field}" value="${esc(settings.columns.join(", "))}">`, "Comma separated, in board order. A status used by a task always gets a column even if listed nowhere here, so nothing goes missing.");
3134
3340
  const git = row("Commits", `<label class="flex items-center gap-2 text-[12.5px] text-zinc-700 dark:text-zinc-300">
3135
- <input type="checkbox" name="gitCommit" class="h-3.5 w-3.5 accent-accent-600" ${settings.gitCommit ? "checked" : ""} ${GIT_COMMIT_ENV ? "disabled" : ""}>
3136
- Commit every board mutation
3137
- </label>`, GIT_COMMIT_ENV ? 'Forced on by <code class="font-mono">BOARD_GIT_COMMIT=1</code>.' : "Each status change or subtask toggle becomes its own commit.");
3341
+ <input type="checkbox" name="gitCommit" class="h-3.5 w-3.5 accent-accent-600" ${settings.gitCommit ? "checked" : ""} ${GIT_COMMIT_ENV ? "disabled" : ""}>
3342
+ Commit every board mutation
3343
+ </label>`, GIT_COMMIT_ENV ? 'Forced on by <code class="font-mono">BOARD_GIT_COMMIT=1</code>.' : "Each status change or subtask toggle becomes its own commit.");
3138
3344
  return `<template id="detail-settings"><div class="detail-root" data-id="settings" data-views="${settings.views.join(",")}">
3139
- <h2 class="text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">Settings</h2>
3140
- <p class="${hint}">Workspace settings live in <code class="font-mono">${SETTINGS_FILENAME}</code> and are meant to be committed. Appearance is per-browser.</p>
3345
+ <h2 class="text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">Settings</h2>
3346
+ <p class="${hint}">Workspace settings live in <code class="font-mono">${SETTINGS_FILENAME}</code> and are meant to be committed. Appearance is per-browser.</p>
3141
3347
 
3142
- <div class="mt-4 border-t border-zinc-100 dark:border-zinc-800">
3143
- ${group("Appearance", "Theme, accent, typeface, size", appearance, true)}
3144
- ${group("Board", "Title, views, columns", board)}
3145
- ${group("Git", GIT_COMMIT_ENV || settings.gitCommit ? "Auto-commit on" : "Auto-commit off", git)}
3146
- </div>
3348
+ <div class="mt-4 border-t border-zinc-100 dark:border-zinc-800">
3349
+ ${group("Appearance", "Theme, accent, typeface, size", appearance, true)}
3350
+ ${group("Board", "Title, views, columns", board)}
3351
+ ${group("Git", GIT_COMMIT_ENV || settings.gitCommit ? "Auto-commit on" : "Auto-commit off", git)}
3352
+ </div>
3147
3353
 
3148
- <p id="settings-error" class="mt-4 hidden rounded-md border border-rose-300 bg-rose-50 px-2.5 py-1.5 text-[12px] text-rose-700 dark:border-rose-500/40 dark:bg-rose-500/10 dark:text-rose-300" role="alert"></p>
3354
+ <p id="settings-error" class="mt-4 hidden rounded-md border border-rose-300 bg-rose-50 px-2.5 py-1.5 text-[12px] text-rose-700 dark:border-rose-500/40 dark:bg-rose-500/10 dark:text-rose-300" role="alert"></p>
3149
3355
 
3150
- <div class="mt-4 flex items-center gap-2 border-t border-zinc-100 pt-4 dark:border-zinc-800">
3151
- <button id="settings-save" type="button"
3152
- class="rounded-md bg-accent-600 px-3 py-1.5 text-[12.5px] font-medium text-white transition-colors hover:bg-accent-500">Save</button>
3153
- <span class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-600">${esc(SETTINGS_FILENAME)}</span>
3154
- </div>
3356
+ <div class="mt-4 flex items-center gap-2 border-t border-zinc-100 pt-4 dark:border-zinc-800">
3357
+ <button id="settings-save" type="button"
3358
+ class="rounded-md bg-accent-600 px-3 py-1.5 text-[12.5px] font-medium text-white transition-colors hover:bg-accent-500">Save</button>
3359
+ <span class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-600">${esc(SETTINGS_FILENAME)}</span>
3360
+ </div>
3155
3361
  </div></template>`;
3156
3362
  }
3363
+ function compareTasks(a, b) {
3364
+ if (a.order !== b.order) {
3365
+ if (a.order === null)
3366
+ return 1;
3367
+ if (b.order === null)
3368
+ return -1;
3369
+ return a.order - b.order;
3370
+ }
3371
+ return (PRIORITY_ORDER[a.priority] ?? 9) - (PRIORITY_ORDER[b.priority] ?? 9) || a.id.localeCompare(b.id);
3372
+ }
3373
+ function siblings(tasks, status, epic) {
3374
+ return tasks.filter((t) => t.status === status && t.epic === epic).sort(compareTasks);
3375
+ }
3376
+ function groupByEpic(cards, epics) {
3377
+ const titles = new Map(epics.map((e) => [e.id, e.title]));
3378
+ const byEpic = new Map;
3379
+ for (const t of cards)
3380
+ byEpic.set(t.epic, [...byEpic.get(t.epic) ?? [], t]);
3381
+ return [...byEpic.entries()].sort(([a], [b]) => a === "" ? 1 : b === "" ? -1 : a.localeCompare(b)).map(([epic, group]) => ({
3382
+ epic,
3383
+ label: epic ? `${epic} ${titles.get(epic) ?? ""}`.trim() : "No epic",
3384
+ tasks: group.sort(compareTasks)
3385
+ }));
3386
+ }
3157
3387
  function appHtml(tasks, epics) {
3158
3388
  const byId = new Map(tasks.map((t) => [t.id, t]));
3159
3389
  const columns = boardColumns(tasks).map((col) => {
3160
- const cards = tasks.filter((t) => t.status === col).sort((a, b) => (PRIORITY_ORDER[a.priority] ?? 9) - (PRIORITY_ORDER[b.priority] ?? 9) || a.id.localeCompare(b.id));
3390
+ const cards = tasks.filter((t) => t.status === col);
3391
+ const groups = groupByEpic(cards, epics);
3392
+ const body = groups.length ? groups.map((g) => `<details class="card-group" open data-group="${esc(col)}/${esc(g.epic)}" data-epic="${esc(g.epic)}">
3393
+ <summary><span class="truncate">${esc(g.label)}</span><span class="card-group-count">${g.tasks.length}</span></summary>
3394
+ <div class="card-group-body" data-drop-epic="${esc(g.epic)}">
3395
+ ${g.tasks.map((t) => cardHtml(t, byId)).join(`
3396
+ `)}
3397
+ </div>
3398
+ </details>`).join(`
3399
+ `) : '<div class="rounded-md border border-dashed border-zinc-200 py-6 text-center text-[12px] text-zinc-300 dark:border-zinc-800 dark:text-zinc-700">No tasks</div>';
3161
3400
  return `<section data-col="${esc(col)}" class="flex w-[290px] shrink-0 flex-col rounded-lg p-1 transition-colors">
3162
- <header class="mb-2.5 flex items-center gap-2 px-1 pt-1">
3163
- ${statusIcon(col)}
3164
- <h2 class="text-[13px] font-medium capitalize text-zinc-700 dark:text-zinc-300">${esc(col.replace("-", " "))}</h2>
3165
- <span class="col-count font-mono text-[11px] text-zinc-400 dark:text-zinc-600">${cards.length}</span>
3166
- </header>
3167
- <div class="flex min-h-[60px] flex-1 flex-col gap-2">
3168
- ${cards.map((t) => cardHtml(t, byId)).join(`
3169
- `) || '<div class="rounded-md border border-dashed border-zinc-200 py-6 text-center text-[12px] text-zinc-300 dark:border-zinc-800 dark:text-zinc-700">No tasks</div>'}
3170
- </div>
3171
- </section>`;
3401
+ <header class="mb-2.5 flex items-center gap-2 px-1 pt-1">
3402
+ ${statusIcon(col)}
3403
+ <h2 class="text-[13px] font-medium capitalize text-zinc-700 dark:text-zinc-300">${esc(col.replace("-", " "))}</h2>
3404
+ <span class="col-count font-mono text-[11px] text-zinc-400 dark:text-zinc-600">${cards.length}</span>
3405
+ </header>
3406
+ <div class="flex min-h-[60px] flex-1 flex-col gap-1.5">
3407
+ ${body}
3408
+ </div>
3409
+ </section>`;
3172
3410
  }).join(`
3173
3411
  `);
3174
3412
  return `${sidebarHtml(epics, tasks)}
@@ -3199,25 +3437,25 @@ var ICON_BUTTON = "rounded p-1 text-zinc-400 hover:bg-zinc-100 hover:text-zinc-6
3199
3437
  function headerHtml(active, meta, showSidebarToggle) {
3200
3438
  return `<header class="flex h-12 items-center gap-3 border-b border-zinc-200 bg-white px-4 dark:border-zinc-800 dark:bg-zinc-950">
3201
3439
  ${showSidebarToggle ? `<button id="sidebar-toggle" type="button" aria-label="Toggle sidebar" title="Toggle sidebar"
3202
- class="hidden ${ICON_BUTTON} md:block">
3203
- <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><rect x="1.5" y="2.5" width="13" height="11" rx="2" stroke="currentColor" stroke-width="1.4"/><path d="M6 2.5 V13.5" stroke="currentColor" stroke-width="1.4"/></svg>
3440
+ class="hidden ${ICON_BUTTON} md:block">
3441
+ <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><rect x="1.5" y="2.5" width="13" height="11" rx="2" stroke="currentColor" stroke-width="1.4"/><path d="M6 2.5 V13.5" stroke="currentColor" stroke-width="1.4"/></svg>
3204
3442
  </button>` : ""}
3205
3443
  <span class="flex items-center gap-2 text-[13px] font-semibold tracking-tight">
3206
- <img src="/logo.svg" width="17" height="17" alt="" class="shrink-0 dark:brightness-125">${esc(settings.title)}
3444
+ <img src="/logo.svg" width="17" height="17" alt="" class="shrink-0 dark:brightness-125">${esc(settings.title)}
3207
3445
  </span>
3208
3446
  ${navTabs(active)}
3209
3447
  <span id="live-dot" class="h-1.5 w-1.5 rounded-full bg-emerald-500" title="Live: file changes appear automatically"></span>
3210
3448
  <div class="ml-auto flex items-center gap-2.5">
3211
- <input id="search" type="search" placeholder="Search" autocomplete="off" spellcheck="false"
3212
- class="hidden w-44 rounded-md border border-zinc-200 bg-zinc-50 px-2.5 py-1 text-[12px] outline-none transition-colors placeholder:text-zinc-400 focus:border-accent-400 dark:border-zinc-800 dark:bg-zinc-900 dark:placeholder:text-zinc-600 dark:focus:border-accent-500 sm:block">
3213
- <div id="header-meta" class="flex items-center gap-2.5">${meta}</div>
3214
- <button type="button" data-open="new" aria-label="New item" title="New epic, story or document" class="${ICON_BUTTON}">
3215
- <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M8 3.5 V12.5 M3.5 8 H12.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
3216
- </button>
3217
- <button id="theme-toggle" type="button" aria-label="Change theme" class="${ICON_BUTTON}"></button>
3218
- <button type="button" data-open="settings" aria-label="Settings" title="Settings" class="${ICON_BUTTON}">
3219
- <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
3220
- </button>
3449
+ <input id="search" type="search" placeholder="Search" autocomplete="off" spellcheck="false"
3450
+ class="hidden w-44 rounded-md border border-zinc-200 bg-zinc-50 px-2.5 py-1 text-[12px] outline-none transition-colors placeholder:text-zinc-400 focus:border-accent-400 dark:border-zinc-800 dark:bg-zinc-900 dark:placeholder:text-zinc-600 dark:focus:border-accent-500 sm:block">
3451
+ <div id="header-meta" class="flex items-center gap-2.5">${meta}</div>
3452
+ <button type="button" data-open="new" aria-label="New item" title="New epic, story or document" class="${ICON_BUTTON}">
3453
+ <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M8 3.5 V12.5 M3.5 8 H12.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
3454
+ </button>
3455
+ <button id="theme-toggle" type="button" aria-label="Change theme" class="${ICON_BUTTON}"></button>
3456
+ <button type="button" data-open="settings" aria-label="Settings" title="Settings" class="${ICON_BUTTON}">
3457
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
3458
+ </button>
3221
3459
  </div>
3222
3460
  </header>`;
3223
3461
  }
@@ -3227,12 +3465,12 @@ var SHEET_HTML = `<div id="backdrop" class="fixed inset-0 z-40 hidden bg-black/2
3227
3465
  <aside id="sheet" tabindex="-1" role="dialog" aria-modal="true" aria-label="Details"
3228
3466
  class="fixed inset-y-0 right-0 z-50 w-full max-w-[460px] translate-x-full overflow-y-auto border-l border-zinc-200 bg-white p-6 shadow-xl outline-none motion-safe:transition-transform motion-safe:duration-200 dark:border-zinc-800 dark:bg-zinc-900">
3229
3467
  <div class="absolute right-4 top-4 flex items-center gap-0.5">
3230
- <button id="sheet-expand" type="button" aria-label="Toggle fullscreen" title="Toggle fullscreen" class="${ICON_BUTTON}">
3231
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M8.5 1.5 H12.5 V5.5 M12.5 1.5 L8 6 M5.5 12.5 H1.5 V8.5 M1.5 12.5 L6 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
3232
- </button>
3233
- <button id="sheet-close" type="button" aria-label="Close" title="Close (Esc)" class="${ICON_BUTTON}">
3234
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M3 3 L11 11 M11 3 L3 11" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
3235
- </button>
3468
+ <button id="sheet-expand" type="button" aria-label="Toggle fullscreen" title="Toggle fullscreen" class="${ICON_BUTTON}">
3469
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M8.5 1.5 H12.5 V5.5 M12.5 1.5 L8 6 M5.5 12.5 H1.5 V8.5 M1.5 12.5 L6 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
3470
+ </button>
3471
+ <button id="sheet-close" type="button" aria-label="Close" title="Close (Esc)" class="${ICON_BUTTON}">
3472
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"><path d="M3 3 L11 11 M11 3 L3 11" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
3473
+ </button>
3236
3474
  </div>
3237
3475
  <div id="sheet-content"></div>
3238
3476
  </aside>
@@ -3260,22 +3498,63 @@ ${SHEET_HTML}
3260
3498
  <script>${board_default}</script>
3261
3499
  </body></html>`;
3262
3500
  }
3263
- function listDocs() {
3264
- const groups = [];
3265
- const rootFiles = readdirSync(PLANNER_DIR).filter((f) => f.endsWith(".md")).sort((a, b) => {
3266
- const ia = ROOT_DOC_ORDER.indexOf(a);
3267
- const ib = ROOT_DOC_ORDER.indexOf(b);
3268
- return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib) || a.localeCompare(b);
3501
+ var MAX_DOC_DEPTH = 8;
3502
+ function readDocDir(rel, depth) {
3503
+ const node = {
3504
+ name: rel === "" ? "planner" : basename(rel),
3505
+ path: rel === "" ? "planner" : rel,
3506
+ files: [],
3507
+ dirs: []
3508
+ };
3509
+ let entries;
3510
+ try {
3511
+ entries = readdirSync(join(PLANNER_DIR, rel), { withFileTypes: true });
3512
+ } catch {
3513
+ return node;
3514
+ }
3515
+ for (const e of entries) {
3516
+ if (e.name.startsWith(".") || DOC_EXCLUDE.has(e.name))
3517
+ continue;
3518
+ const child = rel ? `${rel}/${e.name}` : e.name;
3519
+ if (e.isDirectory()) {
3520
+ if (depth >= MAX_DOC_DEPTH)
3521
+ continue;
3522
+ const sub = readDocDir(child, depth + 1);
3523
+ if (sub.files.length || sub.dirs.length)
3524
+ node.dirs.push(sub);
3525
+ } else if (e.name.endsWith(".md")) {
3526
+ node.files.push(child);
3527
+ }
3528
+ }
3529
+ node.files.sort((a, b) => {
3530
+ if (rel === "") {
3531
+ const ia = ROOT_DOC_ORDER.indexOf(a);
3532
+ const ib = ROOT_DOC_ORDER.indexOf(b);
3533
+ if (ia !== ib)
3534
+ return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
3535
+ }
3536
+ return a.localeCompare(b);
3269
3537
  });
3270
- if (rootFiles.length)
3271
- groups.push({ group: "planner", files: rootFiles });
3272
- const dirs = readdirSync(PLANNER_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && !DOC_EXCLUDE.has(d.name)).map((d) => d.name).sort();
3273
- for (const dir of dirs) {
3274
- const files = readdirSync(join(PLANNER_DIR, dir)).filter((f) => f.endsWith(".md")).sort();
3275
- if (files.length)
3276
- groups.push({ group: dir, files: files.map((f) => `${dir}/${f}`) });
3277
- }
3278
- return groups;
3538
+ node.dirs.sort((a, b) => a.name.localeCompare(b.name));
3539
+ return node;
3540
+ }
3541
+ function listDocs() {
3542
+ const root = readDocDir("", 0);
3543
+ const groups = root.files.length ? [{ ...root, dirs: [] }] : [];
3544
+ return [...groups, ...root.dirs];
3545
+ }
3546
+ function docGroup(rel) {
3547
+ const i = rel.indexOf("/");
3548
+ return i === -1 ? "planner" : rel.slice(0, i);
3549
+ }
3550
+ function allDocFiles() {
3551
+ const out = [];
3552
+ const walk = (d) => {
3553
+ out.push(...d.files);
3554
+ d.dirs.forEach(walk);
3555
+ };
3556
+ listDocs().forEach(walk);
3557
+ return out;
3279
3558
  }
3280
3559
  var RAW_TYPES = {
3281
3560
  svg: "image/svg+xml",
@@ -3356,7 +3635,7 @@ function timelineHtml(rows) {
3356
3635
  while (+cursor < max) {
3357
3636
  const p = pct(+cursor);
3358
3637
  months.push(`<div class="absolute inset-y-0 border-l border-zinc-200 dark:border-zinc-800" style="left:${p.toFixed(2)}%"></div>
3359
- <div class="absolute top-0 -translate-x-1/2 text-[9.5px] font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-600" style="left:${p.toFixed(2)}%">${cursor.toLocaleDateString("en", { month: "short" })}</div>`);
3638
+ <div class="absolute top-0 -translate-x-1/2 text-[9.5px] font-medium uppercase tracking-wide text-zinc-400 dark:text-zinc-600" style="left:${p.toFixed(2)}%">${cursor.toLocaleDateString("en", { month: "short" })}</div>`);
3360
3639
  cursor.setMonth(cursor.getMonth() + 1);
3361
3640
  }
3362
3641
  const bars = rows.map((r) => {
@@ -3367,43 +3646,47 @@ function timelineHtml(rows) {
3367
3646
  const label = `${r.id} ${r.title}`.trim();
3368
3647
  const dates = `${r.start.toISOString().slice(0, 10)} to ${r.end.toISOString().slice(0, 10)}`;
3369
3648
  return `<div class="flex h-8 items-center">
3370
- <div class="w-44 shrink-0 truncate pr-3 text-[12px] text-zinc-600 dark:text-zinc-400" title="${esc(label)}">
3371
- ${r.epic ? `<a href="/#${esc(r.epic)}" class="font-mono text-[10.5px] text-accent-600 hover:underline dark:text-accent-400">${esc(r.epic)}</a> ` : ""}<span class="font-medium text-zinc-800 dark:text-zinc-200">${esc(r.id)}</span> ${esc(r.title)}
3372
- </div>
3373
- <div class="relative h-5 flex-1">
3374
- <div class="track absolute inset-y-0 hidden"></div>
3375
- <div class="absolute inset-y-0 overflow-hidden whitespace-nowrap rounded-md px-2 text-[10px] font-medium leading-5 text-white shadow-sm" style="left:${left.toFixed(2)}%;width:${width.toFixed(2)}%;background:${color}" title="${esc(label)}: ${dates} (${status})">${esc(r.title)}</div>
3376
- </div>
3377
- </div>`;
3649
+ <div class="w-44 shrink-0 truncate pr-3 text-[12px] text-zinc-600 dark:text-zinc-400" title="${esc(label)}">
3650
+ ${r.epic ? `<a href="/#${esc(r.epic)}" class="font-mono text-[10.5px] text-accent-600 hover:underline dark:text-accent-400">${esc(r.epic)}</a> ` : ""}<span class="font-medium text-zinc-800 dark:text-zinc-200">${esc(r.id)}</span> ${esc(r.title)}
3651
+ </div>
3652
+ <div class="relative h-5 flex-1">
3653
+ <div class="track absolute inset-y-0 hidden"></div>
3654
+ <div class="absolute inset-y-0 overflow-hidden whitespace-nowrap rounded-md px-2 text-[10px] font-medium leading-5 text-white shadow-sm" style="left:${left.toFixed(2)}%;width:${width.toFixed(2)}%;background:${color}" title="${esc(label)}: ${dates} (${status})">${esc(r.title)}</div>
3655
+ </div>
3656
+ </div>`;
3378
3657
  }).join("");
3379
3658
  const todayMark = today >= min && today <= max ? `<div class="absolute inset-y-0 z-10 border-l-2 border-rose-500/70" style="left:calc(11rem + (100% - 11rem) * ${(pct(today) / 100).toFixed(4)})">
3380
- <span class="absolute -top-0.5 left-1 text-[9px] font-semibold uppercase tracking-wide text-rose-500">today</span>
3381
- </div>` : "";
3659
+ <span class="absolute -top-0.5 left-1 text-[9px] font-semibold uppercase tracking-wide text-rose-500">today</span>
3660
+ </div>` : "";
3382
3661
  return `<div class="mb-8 rounded-lg border border-zinc-200 bg-white p-4 dark:border-zinc-800 dark:bg-zinc-900">
3383
- <div class="mb-3 flex items-baseline justify-between">
3384
- <span class="text-[11px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Timeline</span>
3385
- <span class="text-[10.5px] text-zinc-400 dark:text-zinc-600">${new Date(min + 2 * DAY).toISOString().slice(0, 10)} to ${new Date(max - 2 * DAY).toISOString().slice(0, 10)}</span>
3386
- </div>
3387
- <div class="relative pt-4">
3388
- <div class="absolute inset-y-0 left-44 right-0">${months.join("")}</div>
3389
- ${todayMark}
3390
- <div class="relative flex flex-col gap-1">${bars}</div>
3391
- </div>
3392
- <div class="mt-3 flex gap-4 text-[10px] text-zinc-400 dark:text-zinc-500">
3393
- <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.done}"></span>done</span>
3394
- <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.active}"></span>active</span>
3395
- <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.pending}"></span>pending</span>
3396
- </div>
3662
+ <div class="mb-3 flex items-baseline justify-between">
3663
+ <span class="text-[11px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Timeline</span>
3664
+ <span class="text-[10.5px] text-zinc-400 dark:text-zinc-600">${new Date(min + 2 * DAY).toISOString().slice(0, 10)} to ${new Date(max - 2 * DAY).toISOString().slice(0, 10)}</span>
3665
+ </div>
3666
+ <div class="relative pt-4">
3667
+ <div class="absolute inset-y-0 left-44 right-0">${months.join("")}</div>
3668
+ ${todayMark}
3669
+ <div class="relative flex flex-col gap-1">${bars}</div>
3670
+ </div>
3671
+ <div class="mt-3 flex gap-4 text-[10px] text-zinc-400 dark:text-zinc-500">
3672
+ <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.done}"></span>done</span>
3673
+ <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.active}"></span>active</span>
3674
+ <span class="inline-flex items-center gap-1.5"><span class="h-2 w-2 rounded-sm" style="background:${TIMELINE_COLOR.pending}"></span>pending</span>
3675
+ </div>
3397
3676
  </div>`;
3398
3677
  }
3399
- function docsNavHtml(groups) {
3400
- return groups.map((g) => `<details class="doc-folder" open data-folder="${esc(g.group)}">
3401
- <summary>${esc(g.group)}<span class="doc-folder-count">${g.files.length}</span></summary>
3402
- ${g.files.map((f) => {
3678
+ function countDocs(d) {
3679
+ return d.files.length + d.dirs.reduce((n, sub) => n + countDocs(sub), 0);
3680
+ }
3681
+ function docsNavHtml(dirs, depth = 0) {
3682
+ return dirs.map((d) => `<details class="doc-folder" open data-folder="${esc(d.path)}" style="--doc-depth:${depth}">
3683
+ <summary>${esc(d.name)}<span class="doc-folder-count">${countDocs(d)}</span></summary>
3684
+ ${docsNavHtml(d.dirs, depth + 1)}
3685
+ ${d.files.map((f) => {
3403
3686
  const name = basename(f);
3404
- return `<a href="/docs?file=${encodeURIComponent(f)}" class="doc-link" data-file="${esc(f)}" title="${esc(f)}">${esc(name)}</a>`;
3687
+ return `<a href="/docs?file=${encodeURIComponent(f)}" class="doc-link" data-file="${esc(f)}" title="${esc(f)}" style="--doc-depth:${depth + 1}">${esc(name)}</a>`;
3405
3688
  }).join("")}
3406
- </details>`).join("");
3689
+ </details>`).join("");
3407
3690
  }
3408
3691
  function docsPageHtml(relFile) {
3409
3692
  const groups = listDocs();
@@ -3418,7 +3701,7 @@ function docsPageHtml(relFile) {
3418
3701
  const parsed = parseFrontmatter(raw);
3419
3702
  const body = parsed ? parsed.body : raw;
3420
3703
  const fm = parsed?.fm ?? {};
3421
- hasMermaid = /^```mermaid/m.test(body);
3704
+ hasMermaid = /^[ \t]*```mermaid/m.test(body);
3422
3705
  const isTimeline = fm.render === "timeline" || basename(relFile).toUpperCase() === "TIMELINE.MD";
3423
3706
  const timeline = isTimeline ? parseTimeline(body) : null;
3424
3707
  const baseDir = dirname(relFile) === "." ? "" : dirname(relFile);
@@ -3427,8 +3710,8 @@ function docsPageHtml(relFile) {
3427
3710
  const seen = new Set;
3428
3711
  const unique = sources.filter((s) => seen.has(s.file) ? false : (seen.add(s.file), true));
3429
3712
  main = `${timeline ? timelineHtml(timeline) : ""}<article class="doc-body">${mdToHtml(body, { docMode: true, baseDir })}</article>
3430
- ${backlinksHtml(unique, "Linked mentions", true)}
3431
- <div class="mt-10 border-t border-zinc-100 pt-3 font-mono text-[10.5px] text-zinc-400 dark:border-zinc-800 dark:text-zinc-600">${esc(relFile)}</div>`;
3713
+ ${backlinksHtml(unique, "Linked mentions", true)}
3714
+ <div class="mt-10 border-t border-zinc-100 pt-3 font-mono text-[10.5px] text-zinc-400 dark:border-zinc-800 dark:text-zinc-600">${esc(relFile)}</div>`;
3432
3715
  }
3433
3716
  return `<!doctype html>
3434
3717
  <html lang="en"><head><meta charset="utf-8">
@@ -3444,22 +3727,22 @@ ${headerHtml("docs", "", true)}
3444
3727
 
3445
3728
  <div class="flex h-[calc((100vh/var(--zoom))-3rem)]">
3446
3729
  <aside id="doc-sidebar" class="hidden w-60 shrink-0 flex-col overflow-y-auto border-r border-zinc-200 bg-white px-2.5 py-2 dark:border-zinc-800 dark:bg-zinc-950 md:flex">
3447
- <div class="mb-1 flex items-center gap-1 px-2 pb-1">
3448
- <span class="text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Files</span>
3449
- <button id="fold-all" type="button" class="${ICON_BUTTON} ml-auto" aria-label="Collapse all folders" title="Collapse all folders">
3450
- <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6.5 8 2.5 12 6.5 M4 9.5 8 13.5 12 9.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
3451
- </button>
3452
- </div>
3453
- <div id="doc-tree">${nav}</div>
3730
+ <div class="mb-1 flex items-center gap-1 px-2 pb-1">
3731
+ <span class="text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">Files</span>
3732
+ <button id="fold-all" type="button" class="${ICON_BUTTON} ml-auto" aria-label="Collapse all folders" title="Collapse all folders">
3733
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6.5 8 2.5 12 6.5 M4 9.5 8 13.5 12 9.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
3734
+ </button>
3735
+ </div>
3736
+ <div id="doc-tree">${nav}</div>
3454
3737
  </aside>
3455
3738
  ${RESIZER_HTML}
3456
3739
  <main id="doc-main" class="flex-1 overflow-y-auto">
3457
- <div id="search-results" class="mx-auto hidden max-w-3xl divide-y divide-zinc-200 px-8 py-5 dark:divide-zinc-800"></div>
3458
- <div id="doc-content" class="mx-auto max-w-3xl px-8 py-8"${abs ? ` data-file="${esc(relFile)}" data-rev="${esc(fileRev(abs))}"` : ""}>${main}</div>
3740
+ <div id="search-results" class="mx-auto hidden max-w-3xl divide-y divide-zinc-200 px-8 py-5 dark:divide-zinc-800"></div>
3741
+ <div id="doc-content" class="mx-auto max-w-3xl px-8 py-8"${abs ? ` data-file="${esc(relFile)}" data-rev="${esc(fileRev(abs))}"` : ""}>${main}</div>
3459
3742
  </main>
3460
3743
  <aside id="doc-outline" class="hidden w-56 shrink-0 overflow-y-auto border-l border-zinc-200 bg-white px-3 py-3 dark:border-zinc-800 dark:bg-zinc-950 lg:block">
3461
- <div class="mb-1.5 px-2 text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">On this page</div>
3462
- <nav id="outline-list"></nav>
3744
+ <div class="mb-1.5 px-2 text-[10.5px] font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500">On this page</div>
3745
+ <nav id="outline-list"></nav>
3463
3746
  </aside>
3464
3747
  </div>
3465
3748
 
@@ -3478,57 +3761,57 @@ function newItemPanelHtml() {
3478
3761
  const columns = boardColumns(allTasks());
3479
3762
  const opt = (v, text) => `<option value="${esc(v)}">${esc(text)}</option>`;
3480
3763
  return `<template id="detail-new"><div class="detail-root" data-id="new">
3481
- <h2 class="text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">New</h2>
3482
- <p class="${hint}">Writes a markdown file into the workspace. Ids and filenames are assigned for you.</p>
3764
+ <h2 class="text-[16px] font-semibold leading-snug text-zinc-900 dark:text-zinc-50">New</h2>
3765
+ <p class="${hint}">Writes a markdown file into the workspace. Ids and filenames are assigned for you.</p>
3483
3766
 
3484
- <div class="mt-4 flex gap-1" data-kind-picker>
3485
- ${[
3767
+ <div class="mt-4 flex gap-1" data-kind-picker>
3768
+ ${[
3486
3769
  ["task", "User story"],
3487
3770
  ["epic", "Epic"],
3488
3771
  ["doc", "Document"]
3489
3772
  ].map(([k, name]) => `<button type="button" class="pick" data-kind="${k}">${name}</button>`).join("")}
3490
- </div>
3773
+ </div>
3491
3774
 
3492
- <div class="mt-4"><label class="${label}" for="new-title">Title</label>
3493
- <input id="new-title" name="title" class="${field}" maxlength="200" placeholder="Short imperative title">
3494
- </div>
3775
+ <div class="mt-4"><label class="${label}" for="new-title">Title</label>
3776
+ <input id="new-title" name="title" class="${field}" maxlength="200" placeholder="Short imperative title">
3777
+ </div>
3495
3778
 
3496
- <div class="mt-3" data-for="doc"><label class="${label}" for="new-path">File path</label>
3497
- <input id="new-path" name="path" class="${field}" placeholder="notes/my-document.md">
3498
- <p class="${hint}">Relative to the workspace root. Folders are created as needed.</p>
3499
- </div>
3779
+ <div class="mt-3" data-for="doc"><label class="${label}" for="new-path">File path</label>
3780
+ <input id="new-path" name="path" class="${field}" placeholder="notes/my-document.md">
3781
+ <p class="${hint}">Relative to the workspace root. Folders are created as needed.</p>
3782
+ </div>
3500
3783
 
3501
- <div class="mt-3 grid grid-cols-2 gap-3" data-for="task">
3502
- <div><label class="${label}" for="new-epic">Epic</label>
3503
- <select id="new-epic" name="epic" class="${field}">
3504
- ${opt("", "(none)")}${epics.map((e) => opt(e.id, `${e.id} ${e.title}`)).join("")}
3505
- </select>
3506
- </div>
3507
- <div><label class="${label}" for="new-priority">Priority</label>
3508
- <select id="new-priority" name="priority" class="${field}">
3509
- ${PRIORITIES.map((p) => opt(p, p)).join("")}
3510
- </select>
3511
- </div>
3512
- <div><label class="${label}" for="new-status">Status</label>
3513
- <select id="new-status" name="status" class="${field}">${columns.map((c) => opt(c, c.replace(/-/g, " "))).join("")}</select>
3514
- </div>
3784
+ <div class="mt-3 grid grid-cols-2 gap-3" data-for="task">
3785
+ <div><label class="${label}" for="new-epic">Epic</label>
3786
+ <select id="new-epic" name="epic" class="${field}">
3787
+ ${opt("", "(none)")}${epics.map((e) => opt(e.id, `${e.id} ${e.title}`)).join("")}
3788
+ </select>
3515
3789
  </div>
3516
-
3517
- <div class="mt-3"><label class="${label}" for="new-body">Description</label>
3518
- <textarea id="new-body" name="body" rows="5" class="${field} resize-y" placeholder="Markdown. Optional."></textarea>
3790
+ <div><label class="${label}" for="new-priority">Priority</label>
3791
+ <select id="new-priority" name="priority" class="${field}">
3792
+ ${PRIORITIES.map((p) => opt(p, p)).join("")}
3793
+ </select>
3519
3794
  </div>
3520
-
3521
- <div class="mt-3" data-for="task"><label class="${label}" for="new-subtasks">Subtasks</label>
3522
- <textarea id="new-subtasks" name="subtasks" rows="3" class="${field} resize-y" placeholder="One per line"></textarea>
3795
+ <div><label class="${label}" for="new-status">Status</label>
3796
+ <select id="new-status" name="status" class="${field}">${columns.map((c) => opt(c, c.replace(/-/g, " "))).join("")}</select>
3523
3797
  </div>
3798
+ </div>
3524
3799
 
3525
- <p id="new-error" class="mt-4 hidden rounded-md border border-rose-300 bg-rose-50 px-2.5 py-1.5 text-[12px] text-rose-700 dark:border-rose-500/40 dark:bg-rose-500/10 dark:text-rose-300" role="alert"></p>
3800
+ <div class="mt-3"><label class="${label}" for="new-body">Description</label>
3801
+ <textarea id="new-body" name="body" rows="5" class="${field} resize-y" placeholder="Markdown. Optional."></textarea>
3802
+ </div>
3526
3803
 
3527
- <div class="mt-4 flex items-center gap-2 border-t border-zinc-100 pt-4 dark:border-zinc-800">
3528
- <button id="new-save" type="button"
3529
- class="rounded-md bg-accent-600 px-3 py-1.5 text-[12.5px] font-medium text-white transition-colors hover:bg-accent-500">Create</button>
3530
- <span id="new-target" class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-600"></span>
3531
- </div>
3804
+ <div class="mt-3" data-for="task"><label class="${label}" for="new-subtasks">Subtasks</label>
3805
+ <textarea id="new-subtasks" name="subtasks" rows="3" class="${field} resize-y" placeholder="One per line"></textarea>
3806
+ </div>
3807
+
3808
+ <p id="new-error" class="mt-4 hidden rounded-md border border-rose-300 bg-rose-50 px-2.5 py-1.5 text-[12px] text-rose-700 dark:border-rose-500/40 dark:bg-rose-500/10 dark:text-rose-300" role="alert"></p>
3809
+
3810
+ <div class="mt-4 flex items-center gap-2 border-t border-zinc-100 pt-4 dark:border-zinc-800">
3811
+ <button id="new-save" type="button"
3812
+ class="rounded-md bg-accent-600 px-3 py-1.5 text-[12.5px] font-medium text-white transition-colors hover:bg-accent-500">Create</button>
3813
+ <span id="new-target" class="font-mono text-[10.5px] text-zinc-400 dark:text-zinc-600"></span>
3814
+ </div>
3532
3815
  </div></template>`;
3533
3816
  }
3534
3817
  var GRAPH_BUTTON = "rounded-md border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-500 transition-colors hover:text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100";
@@ -3550,8 +3833,8 @@ ${headerHtml("graph", `<span class="text-[11px] text-zinc-400 dark:text-zinc-600
3550
3833
  <div id="graph-empty" class="pointer-events-none absolute inset-0 hidden items-center justify-center text-[13px] text-zinc-400 dark:text-zinc-600">No documents to graph yet.</div>
3551
3834
  <div id="graph-hint" class="pointer-events-none absolute bottom-3 left-3 text-[10.5px] text-zinc-400 dark:text-zinc-600">Scroll to zoom · drag to pan · click a note to open it</div>
3552
3835
  <div class="absolute bottom-3 right-3 flex items-center gap-1.5">
3553
- <button id="graph-shape" type="button" class="${GRAPH_BUTTON}">Globe</button>
3554
- <button id="graph-reset" type="button" title="Reset view" class="${GRAPH_BUTTON}">Reset</button>
3836
+ <button id="graph-shape" type="button" class="${GRAPH_BUTTON}">Globe</button>
3837
+ <button id="graph-reset" type="button" title="Reset view" class="${GRAPH_BUTTON}">Reset</button>
3555
3838
  </div>
3556
3839
  </div>
3557
3840
 
@@ -3560,7 +3843,7 @@ ${newItemPanelHtml()}
3560
3843
  ${SHEET_HTML}
3561
3844
 
3562
3845
  <!-- The graph ships with the page instead of as a second request. It is already built here for the
3563
- header count, and one round trip on a cold connection is the slowest part of this view. -->
3846
+ header count, and one round trip on a cold connection is the slowest part of this view. -->
3564
3847
  <script type="application/json" id="graph-data">${JSON.stringify({ nodes, links }).replace(/</g, "\\u003c")}</script>
3565
3848
  <script>${graph_default}</script>
3566
3849
  </body></html>`;
@@ -3634,6 +3917,51 @@ function htmlPage(key, req, render) {
3634
3917
  headers: { "content-type": "text/html; charset=utf-8", etag: hit.etag, "cache-control": "no-cache" }
3635
3918
  });
3636
3919
  }
3920
+ var ORDER_STEP = 100;
3921
+ var ORDER_MIN_GAP = 0.001;
3922
+ function placeInOrder(rest, patch, self) {
3923
+ let index;
3924
+ if (patch.move === "up" || patch.move === "down") {
3925
+ const here = rest.filter((t) => compareTasks(t, self) < 0).length;
3926
+ index = patch.move === "up" ? here - 1 : here + 1;
3927
+ if (index < 0 || index > rest.length)
3928
+ return { own: null, writes: new Map };
3929
+ } else {
3930
+ const anchor = patch.before ?? patch.after;
3931
+ const at = rest.findIndex((t) => t.id === anchor);
3932
+ if (at === -1)
3933
+ return null;
3934
+ index = patch.before !== undefined ? at : at + 1;
3935
+ }
3936
+ const writes = new Map;
3937
+ if (rest.some((t) => t.order === null)) {
3938
+ rest.forEach((t, i) => {
3939
+ const value = (i + 1) * ORDER_STEP;
3940
+ if (t.order !== value)
3941
+ writes.set(t.id, value);
3942
+ t.order = value;
3943
+ });
3944
+ }
3945
+ const ranks = rest.map((t) => t.order);
3946
+ const before = index > 0 ? ranks[index - 1] : null;
3947
+ const after = index < ranks.length ? ranks[index] : null;
3948
+ if (before !== null && after !== null) {
3949
+ if (after - before > ORDER_MIN_GAP)
3950
+ return { own: (before + after) / 2, writes };
3951
+ const respaced = [...rest];
3952
+ respaced.splice(index, 0, self);
3953
+ respaced.forEach((t, i) => {
3954
+ if (t.id !== self.id)
3955
+ writes.set(t.id, (i + 1) * ORDER_STEP);
3956
+ });
3957
+ return { own: (index + 1) * ORDER_STEP, writes };
3958
+ }
3959
+ if (after !== null)
3960
+ return { own: after - ORDER_STEP, writes };
3961
+ if (before !== null)
3962
+ return { own: before + ORDER_STEP, writes };
3963
+ return { own: ORDER_STEP, writes };
3964
+ }
3637
3965
  async function handlePatch(id, req, ctx) {
3638
3966
  const path = findItemPath(id);
3639
3967
  if (!path)
@@ -3675,6 +4003,39 @@ async function handlePatch(id, req, ctx) {
3675
4003
  raw = updated;
3676
4004
  messages.push(`${id}: toggle subtask via board`);
3677
4005
  }
4006
+ if (patch.epic !== undefined) {
4007
+ if (patch.epic !== "" && !allEpics().some((e) => e.id === patch.epic)) {
4008
+ return json({ error: `unknown epic ${patch.epic}` }, 400);
4009
+ }
4010
+ const old = getFrontmatterValue(raw, "epic");
4011
+ if (old !== patch.epic) {
4012
+ raw = setFrontmatterValue(raw, "epic", patch.epic);
4013
+ messages.push(`${id}: epic ${old || "none"} -> ${patch.epic || "none"} via board`);
4014
+ }
4015
+ }
4016
+ if (patch.move !== undefined || patch.before !== undefined || patch.after !== undefined) {
4017
+ const self = allTasks().find((t) => t.id === id);
4018
+ if (!self)
4019
+ return json({ error: `unknown task ${id}` }, 404);
4020
+ const status = patch.status ?? self.status;
4021
+ const epic = patch.epic ?? self.epic;
4022
+ const placed = placeInOrder(siblings(allTasks(), status, epic).filter((t) => t.id !== id), patch, self);
4023
+ if (placed === null)
4024
+ return json({ error: "move target not found in this group" }, 400);
4025
+ if (placed.own !== null) {
4026
+ for (const [target, value] of placed.writes) {
4027
+ if (target === id)
4028
+ continue;
4029
+ const p = findItemPath(target);
4030
+ if (p)
4031
+ writeFileSync2(p, setFrontmatterValue(readFileSync2(p, "utf8"), "order", String(value)));
4032
+ }
4033
+ if (getFrontmatterValue(raw, "order") !== String(placed.own)) {
4034
+ raw = setFrontmatterValue(raw, "order", String(placed.own));
4035
+ messages.push(`${id}: order ${placed.own} via board`);
4036
+ }
4037
+ }
4038
+ }
3678
4039
  const rel = relative(PLANNER_DIR, path);
3679
4040
  if (messages.length === 0) {
3680
4041
  ctx.detail = `${rel} unchanged`;
@@ -3963,8 +4324,8 @@ async function handle(req, ctx) {
3963
4324
  const q = (url.searchParams.get("q") ?? "").trim().toLowerCase();
3964
4325
  const hits = [];
3965
4326
  if (q) {
3966
- for (const g of listDocs()) {
3967
- for (const f of g.files) {
4327
+ for (const f of allDocFiles()) {
4328
+ {
3968
4329
  const abs = safeDocPath(f);
3969
4330
  if (!abs)
3970
4331
  continue;