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 +628 -267
- package/docs/AGENTS.md +1 -0
- package/docs/API.md +14 -1
- package/docs/SPEC.md +9 -0
- package/package.json +1 -1
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
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
-
|
|
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]
|
|
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
|
-
|
|
2988
|
+
const fence = line.match(FENCE);
|
|
2989
|
+
if (fence) {
|
|
2789
2990
|
flushTable();
|
|
2790
2991
|
closeList();
|
|
2791
2992
|
if (!inCode) {
|
|
2792
|
-
|
|
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">' : "
|
|
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>" :
|
|
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(
|
|
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
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
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
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
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
|
-
|
|
2995
|
-
|
|
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
|
-
|
|
3002
|
-
|
|
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
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
</
|
|
3010
|
-
<
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
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
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
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
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
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">·</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
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
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
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
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
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
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
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
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
|
-
|
|
3140
|
-
|
|
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
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
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)
|
|
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
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
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
|
-
|
|
3203
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
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
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
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
|
-
|
|
3264
|
-
|
|
3265
|
-
const
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
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
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
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
|
-
|
|
3381
|
-
|
|
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
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
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
|
|
3400
|
-
return
|
|
3401
|
-
|
|
3402
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
3431
|
-
|
|
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
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
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
|
-
|
|
3458
|
-
|
|
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
|
-
|
|
3462
|
-
|
|
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
|
-
|
|
3482
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3773
|
+
</div>
|
|
3491
3774
|
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
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
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
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
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
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
|
-
|
|
3518
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
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
|
-
|
|
3554
|
-
|
|
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
|
-
|
|
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
|
|
3967
|
-
|
|
4327
|
+
for (const f of allDocFiles()) {
|
|
4328
|
+
{
|
|
3968
4329
|
const abs = safeDocPath(f);
|
|
3969
4330
|
if (!abs)
|
|
3970
4331
|
continue;
|