@jungherz-de/notionkit-elements 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -15
- package/dist/components/nk-bookmark.js +69 -0
- package/dist/components/nk-calendar-view.js +138 -0
- package/dist/components/nk-calendar.js +356 -0
- package/dist/components/nk-copy-field.js +88 -0
- package/dist/components/nk-image-picker.js +130 -0
- package/dist/components/nk-menu.js +2 -14
- package/dist/components/nk-peek.js +122 -0
- package/dist/components/nk-table-view.js +9 -3
- package/dist/components/shared/dates-a32DcW1l.js +67 -0
- package/dist/components/shared/floating-B8CwbXnV.js +22 -0
- package/dist/notionkit-elements.esm.js +974 -20
- package/dist/notionkit-elements.js +979 -19
- package/dist/notionkit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/components/content/nk-bookmark.js +67 -0
- package/src/components/data/nk-calendar-view.js +136 -0
- package/src/components/data/nk-table-view.js +9 -3
- package/src/components/forms/nk-calendar.js +354 -0
- package/src/components/forms/nk-copy-field.js +86 -0
- package/src/components/forms/nk-image-picker.js +128 -0
- package/src/components/overlays/nk-menu.js +2 -14
- package/src/components/overlays/nk-peek.js +120 -0
- package/src/index.js +8 -0
- package/src/util/dates.js +65 -0
- package/src/util/floating.js +20 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// NotionKit v1.
|
|
1
|
+
// NotionKit v1.9.0 – Constructable Stylesheet
|
|
2
2
|
// Auto-generated by build-styles-js.mjs – do not edit manually.
|
|
3
3
|
|
|
4
4
|
// The :root and [data-theme="dark"] blocks that declare --nk-* …
|
|
@@ -6,7 +6,7 @@ const tokensCss = ":root{color-scheme:light;--nk-bg: #ffffff;--nk-bg-sidebar: #f
|
|
|
6
6
|
|
|
7
7
|
// … and everything else, in two pieces around where they were.
|
|
8
8
|
const componentsHead = "[class*=nk-],[class*=nk-] *,[class*=nk-]:before,[class*=nk-]:after,[class*=nk-] *:before,[class*=nk-] *:after{box-sizing:border-box}[class*=nk-] :where(h1,h2,h3,h4,h5,h6,p,figure,blockquote,dl,dd,pre,ul,ol,li){margin:0;padding:0}[class*=nk-] :where(ul,ol){list-style:none}[class*=nk-] :where(button,input,select,textarea,option,optgroup,fieldset,legend),:where(button,input,select,textarea)[class*=nk-]{margin:0;padding:0}[class*=nk-][hidden]:not([hidden=until-found i]){display:none!important}::slotted([hidden]:not([hidden=\"until-found\" i])){display:none!important}";
|
|
9
|
-
const componentsTail = ".nk-body{margin:0;min-height:100vh;min-height:100dvh;font-family:var(--nk-font);font-size:14px;background:var(--nk-bg);color:var(--nk-text);-webkit-font-smoothing:auto;transition:background .25s ease,color .25s ease}.nk-app{display:flex;height:100vh;height:100dvh;overflow:hidden}.nk-sidebar{width:calc(var(--nk-sidebar-width) + env(safe-area-inset-left,0px));min-width:calc(var(--nk-sidebar-width) + env(safe-area-inset-left,0px));padding-left:env(safe-area-inset-left,0px);background:var(--nk-bg-sidebar);display:flex;flex-direction:column;border-right:1px solid var(--nk-border);transition:background .25s ease}.nk-workspace{display:flex;align-items:center;gap:8px;padding:10px 12px;margin:6px 8px 2px;border-radius:var(--nk-radius);cursor:pointer;font-weight:500;user-select:none}.nk-workspace:hover{background:var(--nk-bg-hover)}.nk-workspace .avatar,.nk-workspace ::slotted(.avatar),.nk-workspace ::slotted([slot=\"avatar\"]){width:22px;height:22px;border-radius:4px;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center}.nk-workspace .chev{margin-left:auto;color:var(--nk-text-tertiary);font-size:11px}.nk-sidebar-scroll{flex:1;overflow-y:auto;padding:4px 8px 16px}.nk-sidebar-scroll::-webkit-scrollbar{width:8px}.nk-sidebar-scroll::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:4px}.nk-section-label{font-size:12px;font-weight:500;letter-spacing:.01em;color:var(--nk-text-tertiary);padding:14px 10px 4px;display:flex;justify-content:space-between;align-items:center}.nk-section-label .plus{cursor:pointer;border-radius:4px;padding:0 4px;font-size:13px;opacity:0;transition:opacity .15s}.nk-section-label:hover .plus{opacity:1}.nk-section-label .plus:hover{background:var(--nk-bg-hover)}.nk-sidebar-footer{padding:8px;border-top:1px solid var(--nk-border);color:var(--nk-text-sidebar);font-size:14px}.nk-sidebar-footer .nk-tree-item{min-height:26px}.nk-sidebar-backdrop{display:none;position:fixed;inset:0;z-index:59;background:var(--nk-scrim-soft)}.nk-sidebar-toggle{display:none}.nk-main{flex:1;display:flex;flex-direction:column;min-width:0}.nk-topbar{height:44px;display:flex;align-items:center;padding:0 max(12px,env(safe-area-inset-right,0px)) 0 max(12px,env(safe-area-inset-left,0px));gap:8px;flex-shrink:0}.nk-breadcrumb{display:flex;align-items:center;gap:4px;font-size:14px}.nk-breadcrumb .crumb,.nk-breadcrumb ::slotted(.crumb){padding:2px 6px;border-radius:4px;cursor:pointer;color:var(--nk-text-sidebar);display:flex;align-items:center;gap:5px}.nk-breadcrumb .crumb:hover{background:var(--nk-bg-hover)}a.crumb{text-decoration:none}.nk-breadcrumb .crumb.current,.nk-breadcrumb ::slotted(.crumb.current){color:var(--nk-text)}.nk-breadcrumb .sep{color:var(--nk-text-tertiary);font-size:12px}.nk-topbar-actions{margin-left:auto;display:flex;align-items:center;gap:4px}.nk-topbar-btn{padding:4px 8px;border-radius:var(--nk-radius);cursor:pointer;color:var(--nk-text-sidebar);font-size:14px;user-select:none;border:none;background:transparent;font-family:inherit}.nk-topbar-btn:hover{background:var(--nk-bg-hover)}.nk-topbar-btn svg,.nk-topbar-btn ::slotted(svg){width:16px;height:16px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.nk-share-btn{font-size:14px;padding:4px 8px}.nk-topbar-meta,.nk-topbar-actions ::slotted(.nk-topbar-meta){padding:4px 8px;font-size:12px;color:var(--nk-text-tertiary);white-space:nowrap}.nk-theme-toggle{font-size:15px;width:30px;height:28px;padding:0}.nk-tab-bar{display:none;flex:none;align-items:stretch;gap:2px;position:sticky;bottom:0;z-index:30;box-sizing:border-box;height:calc(var(--nk-tab-bar-height) - 6px + max(6px,env(safe-area-inset-bottom,0px)));padding:6px max(4px,env(safe-area-inset-right,0px)) max(6px,env(safe-area-inset-bottom,0px)) max(4px,env(safe-area-inset-left,0px));background:var(--nk-bg-sidebar);border-top:1px solid var(--nk-border)}.nk-tab-bar.always{display:flex}.nk-tab-bar.fixed{position:fixed;left:0;right:0;bottom:0}.nk-tab-bar-spacer{display:none;flex:none;height:calc(var(--nk-tab-bar-height) - 6px + max(6px,env(safe-area-inset-bottom,0px)))}.nk-tab-bar.always.fixed+.nk-tab-bar-spacer{display:block}.nk-tab-bar.floating{position:fixed;left:max(12px,env(safe-area-inset-left,0px));right:max(12px,env(safe-area-inset-right,0px));bottom:calc(12px + env(safe-area-inset-bottom,0px));height:var(--nk-tab-bar-height);padding:6px;border:1px solid var(--nk-border);border-radius:16px;box-shadow:var(--nk-shadow-menu)}.nk-tab-bar-item{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;padding:4px 2px;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:10.5px;line-height:1.2;color:var(--nk-text-secondary);text-decoration:none;cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent}.nk-tab-bar-item:hover{color:var(--nk-text);background:var(--nk-bg-hover)}.nk-tab-bar-item.active{color:var(--nk-accent)}.nk-tab-bar-item:disabled{opacity:.5;cursor:not-allowed}.nk-tab-bar-item .icon,.nk-tab-bar-item ::slotted([slot=\"icon\"]){font-size:20px;line-height:1}.nk-tab-bar-item .label,.nk-tab-bar-item ::slotted(.label){max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nk-tree-item{display:flex;align-items:center;gap:6px;padding:3px 8px 3px 10px;border-radius:var(--nk-radius);cursor:pointer;user-select:none;color:var(--nk-text-sidebar);position:relative;min-height:var(--_nk-row, 28px)}.nk-tree-item:hover{background:var(--nk-bg-hover)}.nk-tree-item.active{background:var(--nk-bg-active);color:var(--nk-text);font-weight:500}.nk-tree-item.compact{min-height:26px}.nk-tree-item .icon,.nk-tree-item ::slotted(.icon),.nk-tree-item ::slotted([slot=\"icon\"]){font-size:15px;width:20px;text-align:center;flex-shrink:0}.nk-tree-item .label,.nk-tree-item ::slotted(.label){white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-tree-item .actions{margin-left:auto;display:none;gap:2px;color:var(--nk-text-tertiary)}.nk-tree-item:hover .actions{display:flex}.nk-tree-item .actions span{padding:0 3px;border-radius:3px;font-size:12px}.nk-tree-item .actions span:hover{background:var(--nk-bg-active)}.nk-tree-children{margin-left:14px;border-left:1px solid var(--nk-border);padding-left:4px;overflow:hidden}.nk-tree-children.collapsed{display:none}.nk-toggle-arrow{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:9px;color:var(--nk-text-tertiary);border-radius:3px;transition:transform .15s}.nk-toggle-arrow.open{transform:rotate(90deg)}.nk-kbd-hint{margin-left:auto;display:flex;gap:3px;align-items:center}.nk-kbd{font-family:inherit;font-size:10.5px;background:var(--nk-bg-callout);border:1px solid var(--nk-border-strong);border-bottom-width:2px;border-radius:4px;padding:0 4px}.nk-page-scroll{flex:1;overflow-y:auto}.nk-page-scroll::-webkit-scrollbar{width:10px}.nk-page-scroll::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:5px;border:2px solid var(--nk-bg)}.nk-cover{height:200px;background:radial-gradient(ellipse at 20% 40%,color-mix(in srgb,var(--nk-decor-purple) 35%,transparent),transparent 55%),radial-gradient(ellipse at 80% 20%,color-mix(in srgb,var(--nk-decor-blue) 35%,transparent),transparent 55%),radial-gradient(ellipse at 60% 90%,color-mix(in srgb,var(--nk-decor-orange) 25%,transparent),transparent 55%),var(--nk-bg-callout)}.nk-cover>img,.nk-cover ::slotted(img){display:block;width:100%;height:100%;object-fit:cover}.nk-page{max-width:760px;margin:0 auto;padding:24px max(64px,env(safe-area-inset-right,0px)) 120px max(64px,env(safe-area-inset-left,0px));font-size:16px;line-height:1.5}.nk-page.full{max-width:none}.nk-page.small{font-size:14px}.nk-cover+.nk-page,.nk-page.covered{padding-top:0}.nk-page-icon,.nk-page ::slotted(.nk-page-icon),.nk-page ::slotted([slot=\"icon\"]){font-size:64px;line-height:1;margin-top:0;cursor:pointer;user-select:none;display:inline-block}.nk-cover+.nk-page .nk-page-icon,.nk-cover+.nk-page ::slotted(.nk-page-icon),.nk-cover+.nk-page ::slotted([slot=\"icon\"]),.nk-page.covered .nk-page-icon,.nk-page.covered ::slotted(.nk-page-icon),.nk-page.covered ::slotted([slot=\"icon\"]){margin-top:-42px}.nk-page-title{font-size:40px;font-weight:700;line-height:1.2;margin:8px 0 4px;outline:none;letter-spacing:0}.nk-page-meta{color:var(--nk-text-tertiary);font-size:13px;margin-bottom:24px;display:flex;gap:16px}.nk-props{display:flex;flex-direction:column;margin:0 0 20px;font-size:14px;line-height:1.5}.nk-prop{display:flex;align-items:flex-start;min-width:0}.nk-prop .p-name{flex:0 0 160px;min-width:0;min-height:34px;padding:0 6px;display:flex;align-items:center;gap:6px;overflow:hidden;border-radius:var(--nk-radius);color:var(--nk-text-secondary);white-space:nowrap;user-select:none}.nk-prop .p-icon,.nk-prop ::slotted([slot=\"icon\"]){width:16px;flex-shrink:0;text-align:center;font-size:13px}.nk-prop .p-value{flex:1 1 auto;min-width:0;min-height:34px;padding:5px 8px;display:flex;align-items:center;flex-wrap:wrap;gap:4px 6px;border-radius:var(--nk-radius);overflow-wrap:anywhere}.nk-prop .p-name:hover,.nk-prop .p-value:hover{background:var(--nk-bg-hover)}.nk-page p.lead{font-size:1em;line-height:1.6;color:var(--nk-text-secondary);margin-bottom:20px}.nk-page ::slotted(p.lead){font-size:1em;line-height:1.6;color:var(--nk-text-secondary);margin-bottom:20px!important}.nk-heading{font-size:1.5em;font-weight:600;line-height:1.3;margin:32px 0 10px;display:flex;align-items:center;gap:8px}.nk-callout{display:flex;gap:10px;align-items:flex-start;background:var(--nk-bg-callout);border-radius:var(--nk-radius);padding:16px 16px 16px 12px;margin:16px 0;line-height:1.5}.nk-callout .c-icon,.nk-callout ::slotted(.c-icon),.nk-callout ::slotted([slot=\"icon\"]){font-size:17px}.nk-todo{display:flex;align-items:flex-start;gap:8px;padding:4px 0}.nk-todo input[type=checkbox]{appearance:none;width:16px;height:16px;margin-top:3px;border:1.4px solid var(--nk-border-strong);border-radius:2px;cursor:pointer;flex-shrink:0;position:relative;background:var(--nk-bg)}.nk-todo input[type=checkbox]:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-todo input[type=checkbox]:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:11px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-todo input:checked+span{text-decoration:line-through;color:var(--nk-text-tertiary)}.nk-todo input:disabled{opacity:.5;cursor:not-allowed}.nk-toggle{margin:6px 0}.nk-toggle summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:var(--nk-radius);font-weight:500;user-select:none}.nk-toggle summary::-webkit-details-marker{display:none}.nk-toggle summary:hover{background:var(--nk-bg-hover)}.nk-toggle summary:before{content:\"\\25b8\";color:var(--nk-text-tertiary);font-size:11px;transition:transform .15s;display:inline-block}.nk-toggle[open] summary:before{transform:rotate(90deg)}.nk-toggle .toggle-body,.nk-toggle ::slotted(.toggle-body){padding:4px 0 8px 26px;color:var(--nk-text-secondary);line-height:1.55}.nk-divider{border:none;border-top:1px solid var(--nk-border);margin:24px 0}.nk-quote{border-left:3px solid var(--nk-text);padding:2px 0 2px 14px;margin:16px 0;color:var(--nk-text-secondary);line-height:1.5}.nk-quote .q-cite{display:block;margin-top:6px;font-size:12.5px;color:var(--nk-text-tertiary)}.nk-mention{display:inline-flex;align-items:center;gap:4px;padding:0 4px;border-radius:4px;font-weight:500;cursor:pointer;white-space:nowrap}.nk-mention:hover{background:var(--nk-bg-hover)}.nk-mention.person{color:var(--nk-text)}.nk-mention.person .mini-avatar,.nk-mention.person .nk-avatar,.nk-mention.person ::slotted(.mini-avatar),.nk-mention.person ::slotted([slot=\"avatar\"]){width:16px;height:16px;border-radius:50%;color:var(--nk-on-accent);font-size:8.5px;font-weight:600;display:inline-flex;align-items:center;justify-content:center}.nk-mention.page{color:var(--nk-text-secondary);text-decoration:underline;text-decoration-color:var(--nk-border-strong);text-underline-offset:2px}.nk-mention.date{color:var(--nk-color-orange)}.nk-inline-code{font-family:var(--nk-font-mono);font-size:85%;color:var(--nk-danger);background:color-mix(in srgb,var(--nk-danger) 8%,transparent);border-radius:4px;padding:1px 5px}.nk-code{background:var(--nk-bg-code);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:20px 24px;font-family:var(--nk-font-mono);font-size:13px;line-height:1.6;margin:14px 0;overflow-x:auto;color:var(--nk-text-secondary);white-space:pre;position:relative}.nk-code .lang{position:absolute;top:6px;right:10px;font-size:11px;color:var(--nk-text-tertiary);font-family:var(--nk-font)}.nk-code .tag,.nk-code ::slotted(.tag){color:var(--nk-accent)}.nk-code .attr,.nk-code ::slotted(.attr){color:var(--nk-color-orange)}.nk-database{margin:12px 0 8px}.nk-db-tabs{display:flex;gap:2px;align-items:center;padding:0 0 6px;margin-bottom:0;font-size:14px}.nk-db-tab{padding:4px 8px;cursor:pointer;color:var(--nk-text-secondary);border-radius:var(--nk-radius);user-select:none;line-height:20px;display:flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap}.nk-db-tab:hover{color:var(--nk-text);background:var(--nk-bg-hover)}.nk-db-tab.active{color:var(--nk-text);background:var(--nk-bg-active);font-weight:500}.nk-db-tab.add{color:var(--nk-text-tertiary)}.nk-db-tab .badge,.nk-db-tab ::slotted(.badge){background:var(--nk-bg-callout);border-radius:8px;font-size:11px;padding:0 6px;color:var(--nk-text-tertiary)}.nk-db-toolbar{display:flex;align-items:center;gap:8px;min-width:0;padding-bottom:6px}.nk-db-toolbar>.nk-db-tabs{flex:1 1 auto;min-width:0;padding-bottom:0;overflow-x:auto;scrollbar-width:none}.nk-db-toolbar>.nk-db-tabs::-webkit-scrollbar{display:none}.nk-db-toolbar .tools{flex:none;display:flex;align-items:center;gap:4px;margin-left:auto}.nk-db-tool{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 8px;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:14px;color:var(--nk-text-secondary);white-space:nowrap;cursor:pointer;user-select:none}.nk-db-tool:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-db-tool.active{color:var(--nk-accent)}.nk-filter-row{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:2px 0 8px}.nk-filter-pill{display:inline-flex;align-items:center;gap:4px;height:24px;padding:0 8px;border:1px solid var(--nk-border-strong);border-radius:12px;background:transparent;font-family:inherit;font-size:13px;line-height:1;color:var(--nk-text-secondary);white-space:nowrap;cursor:pointer;user-select:none}.nk-filter-pill:hover{background:var(--nk-bg-hover)}.nk-filter-pill.active{color:var(--nk-accent);border-color:color-mix(in srgb,var(--nk-accent) 35%,transparent);background:color-mix(in srgb,var(--nk-accent) 6%,transparent)}.nk-filter-pill.add{border-color:transparent;color:var(--nk-text-tertiary)}.nk-filter-pill.add:hover{color:var(--nk-text-secondary)}.nk-filter-pill button{padding:0;border:none;background:none;font:inherit;color:inherit;cursor:pointer}.nk-filter-pill .fp-remove{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:-4px;border-radius:50%;font-size:13px}.nk-filter-pill .fp-remove:hover{background:color-mix(in srgb,currentColor 15%,transparent)}.nk-table-wrap{overflow-x:auto}.nk-table{width:100%;border-collapse:collapse;font-size:14px}.nk-table th{text-align:left;font-weight:400;color:var(--nk-text-secondary);height:36px;padding:0 8px;border-bottom:1px solid var(--nk-border);border-right:1px solid var(--nk-border);font-size:14px;white-space:nowrap;user-select:none;cursor:pointer}.nk-table th:hover{background:var(--nk-bg-hover)}.nk-table th .th-icon,.nk-table th ::slotted(.th-icon){margin-right:6px;font-size:13px;color:var(--nk-text-tertiary)}.nk-table td{height:36px;padding:6px 8px;line-height:1.5;border-bottom:1px solid var(--nk-border);border-right:1px solid var(--nk-border);white-space:nowrap;vertical-align:middle}.nk-table th:last-child,.nk-table td:last-child{border-right:none}.nk-table.wrap td,.nk-table td.wrap{white-space:normal;vertical-align:top}.nk-table tbody tr:hover{background:var(--nk-bg-hover)}.nk-table .row-title{display:flex;align-items:center;gap:7px;font-weight:500;cursor:pointer}.nk-table .row-title:hover{text-decoration:underline;text-decoration-color:var(--nk-text-tertiary)}.nk-table .date-cell{color:var(--nk-text-secondary)}.nk-table .num{text-align:right;font-variant-numeric:tabular-nums}.nk-table .person-cell{display:flex;align-items:center;gap:6px;color:var(--nk-text-secondary)}.nk-table .person-cell .mini-avatar,.nk-table .person-cell ::slotted(.mini-avatar){width:20px;height:20px;border-radius:50%;font-size:10px;color:var(--nk-on-accent);display:inline-flex;align-items:center;justify-content:center;font-weight:600}.nk-new-row,.nk-table .new-row{color:var(--nk-text-tertiary);cursor:pointer;padding:8px;display:flex;align-items:center;gap:7px;font-size:14px}.nk-new-row:hover,.nk-table .new-row:hover{background:var(--nk-bg-hover)}.nk-tag{display:inline-flex;align-items:center;max-width:100%;height:20px;padding:0 6px;border-radius:3px;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;background:var(--nk-tag-gray-bg);color:var(--nk-tag-gray-text)}.nk-tag.gray{background:var(--nk-tag-gray-bg);color:var(--nk-tag-gray-text)}.nk-tag.brown{background:var(--nk-tag-brown-bg);color:var(--nk-tag-brown-text)}.nk-tag.orange{background:var(--nk-tag-orange-bg);color:var(--nk-tag-orange-text)}.nk-tag.yellow{background:var(--nk-tag-yellow-bg);color:var(--nk-tag-yellow-text)}.nk-tag.green{background:var(--nk-tag-green-bg);color:var(--nk-tag-green-text)}.nk-tag.blue{background:var(--nk-tag-blue-bg);color:var(--nk-tag-blue-text)}.nk-tag.purple{background:var(--nk-tag-purple-bg);color:var(--nk-tag-purple-text)}.nk-tag.pink{background:var(--nk-tag-pink-bg);color:var(--nk-tag-pink-text)}.nk-tag.red{background:var(--nk-tag-red-bg);color:var(--nk-tag-red-text)}.nk-progress{width:110px;height:6px;border-radius:3px;background:var(--nk-tint-blue);overflow:hidden;display:inline-block}.nk-progress>i{display:block;height:100%;background:var(--nk-color-blue);border-radius:3px}.nk-progress.wide{width:100%;flex:1 1 60px}.nk-progress-label{font-size:12px;color:var(--nk-text-tertiary);margin-left:7px;white-space:nowrap}.nk-list{display:flex;flex-direction:column;font-size:14px}.nk-list-item{display:flex;align-items:center;gap:8px;min-width:0;overflow:hidden;min-height:36px;padding:4px 6px;border-bottom:1px solid var(--nk-border);color:inherit;text-decoration:none;cursor:pointer}.nk-list-item:hover{background:var(--nk-bg-hover)}.nk-list>.nk-list-item:last-child,.nk-list ::slotted(.nk-list-item:last-child),.nk-list-item.last{border-bottom:none}.nk-list-item .l-icon,.nk-list-item ::slotted([slot=\"icon\"]){width:20px;flex-shrink:0;text-align:center;font-size:15px}.nk-list-item .l-title,.nk-list-item ::slotted(.l-title){flex:1 1 auto;min-width:0;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-list-item .l-meta,.nk-list-item ::slotted(.l-meta){flex:none;display:flex;align-items:center;gap:8px;margin-left:auto;font-size:12px;color:var(--nk-text-secondary);white-space:nowrap}.nk-board{display:none;gap:12px;padding:14px 2px;overflow-x:auto}.nk-board.active{display:flex}.nk-board-col{min-width:220px;width:220px;flex-shrink:0}.nk-board-col-header{display:flex;align-items:center;gap:7px;margin-bottom:8px;font-size:13.5px;font-weight:500}.nk-board-col-header .count{color:var(--nk-text-tertiary);font-weight:400}.nk-card{background:var(--nk-bg-card);border:1px solid var(--nk-border);border-radius:8px;padding:10px 12px;margin-bottom:8px;cursor:grab;box-shadow:var(--nk-shadow-card);transition:border-color .15s}.nk-card:hover{border-color:var(--nk-border-strong)}.nk-card .card-title,.nk-card ::slotted(.card-title){font-weight:500;margin-bottom:7px;display:flex;gap:6px;align-items:center}.nk-card .card-meta,.nk-card ::slotted(.card-meta){display:flex;gap:6px;flex-wrap:wrap;align-items:center;font-size:12px;color:var(--nk-text-secondary)}.nk-field{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:9px 0}.nk-field .f-label,.nk-field ::slotted(.f-label),.nk-field ::slotted([slot=\"label\"]){font-size:14px}.nk-field .f-desc,.nk-field ::slotted(.f-desc),.nk-field ::slotted([slot=\"desc\"]){font-size:12px;color:var(--nk-text-secondary);margin-top:2px;line-height:1.45}.nk-field .f-control,.nk-field ::slotted(.f-control){flex-shrink:0}.nk-field.stacked,.nk-fields>.nk-field{flex-direction:column;align-items:stretch;gap:6px;min-width:0}.nk-field.stacked .f-control,.nk-fields>.nk-field .f-control{width:100%;min-width:0}.nk-field.stacked .nk-input,.nk-field.stacked .nk-textarea,.nk-field.stacked .nk-select,.nk-fields>.nk-field .nk-input,.nk-fields>.nk-field .nk-textarea,.nk-fields>.nk-field .nk-select{width:100%;min-width:0}.nk-field.compact,.nk-fields>.nk-field{padding:0;gap:4px;min-width:0}.nk-field.compact .f-label,.nk-field.compact ::slotted([slot=\"label\"]),.nk-fields>.nk-field .f-label,.nk-fields>.nk-field ::slotted([slot=\"label\"]){font-size:12px;color:var(--nk-text-tertiary)}.nk-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px 12px;padding:9px 0}.nk-fields>.nk-field{min-width:0}.nk-input,.nk-select,.nk-textarea{font-family:inherit;font-size:14px;line-height:20px;color:var(--nk-text);background:var(--nk-bg-input);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:5px 10px;outline:none;transition:border-color .15s,box-shadow .15s;min-width:210px}.nk-input:hover,.nk-select:hover,.nk-textarea:hover{border-color:var(--nk-border-strong)}.nk-input:focus,.nk-select:focus,.nk-textarea:focus{border-color:color-mix(in srgb,var(--nk-accent) 60%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 30%,transparent)}.nk-input::placeholder,.nk-textarea::placeholder{color:var(--nk-text-tertiary)}.nk-input.wide,.nk-textarea.wide,.nk-select.wide{width:100%;min-width:0}.nk-input[type=date],.nk-input[type=time],.nk-input[type=datetime-local],.nk-input[type=month]{appearance:none}.nk-input::-webkit-date-and-time-value{text-align:start;min-height:1lh}.nk-select.compact{min-width:120px}.nk-textarea{resize:vertical;min-height:70px;line-height:1.5}.nk-select{appearance:none;cursor:pointer;padding-right:26px;background-image:linear-gradient(45deg,transparent 50%,var(--nk-text-tertiary) 50%),linear-gradient(135deg,var(--nk-text-tertiary) 50%,transparent 50%);background-position:calc(100% - 14px) 55%,calc(100% - 10px) 55%;background-size:4px 4px;background-repeat:no-repeat}.nk-btn{font-family:inherit;font-size:14px;line-height:20px;font-weight:500;border-radius:var(--nk-radius);cursor:pointer;padding:3px 12px;border:1px solid transparent;transition:background .15s,border-color .15s,box-shadow .15s,opacity .15s;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}.nk-btn svg,.nk-btn ::slotted(svg){width:15px;height:15px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.nk-btn.primary{background:var(--nk-accent);color:var(--nk-on-accent)}.nk-btn.primary:hover{opacity:.88}.nk-btn.secondary{background:var(--nk-bg-card);color:var(--nk-text);box-shadow:var(--nk-shadow-btn)}.nk-btn.secondary:hover{background:color-mix(in srgb,var(--nk-bg-card),var(--nk-text) 6%)}.nk-btn.danger{background:var(--nk-bg-card);color:var(--nk-danger);box-shadow:var(--nk-shadow-btn)}.nk-btn.danger:hover{background:color-mix(in srgb,var(--nk-danger) 8%,var(--nk-bg-card))}.nk-btn.danger-solid{background:var(--nk-danger);color:var(--nk-on-accent)}.nk-btn.danger-solid:hover{opacity:.88}.nk-btn.small{padding:1px 8px;font-size:13px;line-height:20px}a.nk-btn{text-decoration:none}.nk-btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.nk-switch{position:relative;width:34px;height:20px;flex-shrink:0;appearance:none;border:none;cursor:pointer;border-radius:20px;background:var(--nk-border-strong);transition:background .2s}.nk-switch:after{content:\"\";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--nk-on-accent);transition:transform .2s;box-shadow:var(--nk-shadow-knob)}.nk-switch:checked,.nk-switch[aria-checked=true]{background:var(--nk-accent)}.nk-switch:checked:after,.nk-switch[aria-checked=true]:after{transform:translate(14px)}.nk-switch:disabled{opacity:.5;cursor:not-allowed}.nk-switch-label{display:inline-flex;align-items:flex-start;gap:8px;font-size:14px;cursor:pointer}.nk-switch-label>.nk-switch{font-size:inherit;line-height:inherit;margin-top:max(0px,calc((1lh - 20px)/2))}.nk-switch-label>span{padding-top:max(0px,calc((20px - 1lh)/2))}.nk-switch-label:has(.nk-switch:disabled){cursor:not-allowed;color:var(--nk-text-tertiary)}.nk-check{display:flex;align-items:flex-start;gap:8px;padding:4px 0;font-size:14px;cursor:pointer}.nk-check input{appearance:none;width:16px;height:16px;flex-shrink:0;border:1.4px solid var(--nk-border-strong);border-radius:3px;cursor:pointer;position:relative;background:var(--nk-bg);font-size:inherit;line-height:inherit;margin-top:max(0px,calc((1lh - 16px)/2))}.nk-check input[type=radio]{border-radius:50%}.nk-check input:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-check input:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:10.5px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-check input[type=radio]:checked:after{content:\"\\25cf\";font-size:7px}.nk-check input:disabled{opacity:.5;cursor:not-allowed}.nk-check input:disabled+*{opacity:.6}.nk-slider{width:210px;accent-color:var(--nk-accent);cursor:pointer}.nk-slider-value{font-size:12.5px;color:var(--nk-text-tertiary);margin-top:3px}.nk-profile-row{display:flex;align-items:center;gap:14px;padding:8px 0}.nk-profile-row .big-avatar,.nk-profile-row ::slotted(.big-avatar),.nk-profile-row ::slotted([slot=\"avatar\"]){width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:20px;font-weight:600;display:flex;align-items:center;justify-content:center}.nk-model-card{border:1px solid var(--nk-border-strong);border-radius:8px;padding:12px 14px;margin-bottom:10px;cursor:pointer;display:flex;align-items:flex-start;gap:11px;transition:border-color .15s,background .15s}.nk-model-card:hover{background:var(--nk-bg-hover)}.nk-model-card.selected{border-color:var(--nk-accent);background:color-mix(in srgb,var(--nk-accent) 6%,transparent)}.nk-model-card .m-radio{width:15px;height:15px;border-radius:50%;flex-shrink:0;margin-top:2px;border:1.4px solid var(--nk-border-strong);position:relative}.nk-model-card.selected .m-radio{border-color:var(--nk-accent)}.nk-model-card.selected .m-radio:after{content:\"\";position:absolute;inset:3px;border-radius:50%;background:var(--nk-accent)}.nk-model-card .m-name,.nk-model-card ::slotted(.m-name),.nk-model-card ::slotted([slot=\"title\"]){font-weight:500;font-size:14px;display:flex;align-items:center;gap:7px}.nk-model-card .m-desc,.nk-model-card ::slotted(.m-desc),.nk-model-card ::slotted([slot=\"desc\"]){font-size:12px;color:var(--nk-text-secondary);margin-top:2px;line-height:1.45}.nk-danger-zone{border:1px solid color-mix(in srgb,var(--nk-danger) 40%,transparent);border-radius:8px;padding:14px 16px;margin-top:26px}.nk-danger-zone .dz-title{color:var(--nk-danger);font-weight:600;font-size:13px;margin-bottom:8px}.nk-member-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--nk-border)}.nk-member-list>.nk-member-row:last-child,.nk-member-list ::slotted(.nk-member-row:last-child),.nk-member-row.last{border-bottom:none}.nk-member-row .mini-avatar,.nk-member-row .nk-avatar,.nk-member-row ::slotted(.mini-avatar),.nk-member-row ::slotted([slot=\"avatar\"]){width:28px;height:28px;border-radius:50%;color:var(--nk-on-accent);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;flex-shrink:0}.nk-member-row>:has(>.m-mail){min-width:0}.nk-member-row .m-mail{font-size:12px;color:var(--nk-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nk-member-row .nk-select{min-width:120px;margin-left:auto}.nk-member-row ::slotted([slot=\"role\"]){margin-left:auto}.nk-modal-backdrop{position:fixed;inset:0;background:var(--nk-scrim);padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);display:flex;align-items:center;justify-content:center;z-index:100;opacity:0;pointer-events:none;transition:opacity .2s ease}.nk-modal-backdrop.open{opacity:1;pointer-events:auto}.nk-modal{width:min(1150px,92vw);height:min(715px,86vh);max-width:100%;max-height:100%;background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);display:flex;overflow:hidden;transform:scale(.98) translateY(6px);transition:transform .2s ease}.nk-modal-backdrop.open .nk-modal{transform:scale(1) translateY(0)}.nk-settings-nav{width:240px;min-width:240px;background:var(--nk-bg-sidebar);border-right:1px solid var(--nk-border);padding:10px 8px;overflow-y:auto;flex-shrink:0}.nk-settings-user{display:flex;align-items:center;gap:9px;padding:6px 10px 12px;margin-bottom:4px}.nk-settings-user .avatar,.nk-settings-user ::slotted(.avatar),.nk-settings-user ::slotted([slot=\"avatar\"]){width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-weight:600;font-size:13px;display:flex;align-items:center;justify-content:center}.nk-settings-user .name{font-weight:500;font-size:14px}.nk-settings-user .mail{font-size:12px;color:var(--nk-text-secondary)}.nk-settings-nav .nk-tree-item{min-height:28px}.nk-settings-nav .nk-tree-item.active{background:var(--nk-bg-active);color:var(--nk-text);font-weight:500}.nk-settings-content{flex:1;overflow-y:auto;padding:36px 60px 80px;min-width:0}.nk-settings-content::-webkit-scrollbar{width:10px}.nk-settings-content::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:5px;border:2px solid var(--nk-bg)}.nk-settings-pane{display:none;max-width:800px}.nk-settings-pane.active{display:block}.nk-settings-pane>h2{font-size:22px;font-weight:600;line-height:1.3;margin-bottom:20px}.nk-settings-pane>h3{font-size:16px;font-weight:500;padding-bottom:8px;border-bottom:1px solid var(--nk-border);margin:30px 0 12px}.nk-settings-pane ::slotted(h2){font-size:22px;font-weight:600;line-height:1.3;padding:0!important;margin:0 0 20px!important}.nk-settings-pane ::slotted(h3){font-size:16px;font-weight:500;border:0;border-bottom:1px solid var(--nk-border);padding:0 0 8px!important;margin:30px 0 12px!important}.nk-pop{background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);padding:10px;width:296px}.nk-emoji-search{width:100%;font-family:inherit;font-size:14px;color:var(--nk-text);background:var(--nk-bg-input);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:6px 10px;outline:none;margin-bottom:8px}.nk-emoji-grid{display:grid;grid-template-columns:repeat(8,1fr);gap:2px}.nk-emoji-grid span,.nk-emoji-grid ::slotted(span){font-size:18px;text-align:center;padding:4px 0;border-radius:5px;cursor:pointer;user-select:none}.nk-emoji-grid span:hover{background:var(--nk-bg-hover)}.nk-emoji-cats{display:flex;gap:2px;margin-top:8px;padding-top:8px;border-top:1px solid var(--nk-border)}.nk-emoji-cats span{font-size:14px;padding:3px 7px;border-radius:5px;cursor:pointer;color:var(--nk-text-tertiary);filter:grayscale(1);opacity:.6}.nk-emoji-cats span.active,.nk-emoji-cats span:hover{filter:none;opacity:1;background:var(--nk-bg-hover)}.nk-menu{padding:5px;width:230px}.nk-menu-item{display:flex;align-items:center;gap:9px;padding:4px 8px;min-height:var(--_nk-row, 28px);border-radius:5px;cursor:pointer;font-size:14px;user-select:none}.nk-menu-item:hover{background:var(--nk-bg-hover)}.nk-menu-item .m-icon,.nk-menu-item ::slotted(.m-icon),.nk-menu-item ::slotted([slot=\"icon\"]){width:17px;text-align:center;font-size:14px}.nk-menu-item .m-shortcut,.nk-menu-item ::slotted(.m-shortcut){margin-left:auto;font-size:12px;color:var(--nk-text-tertiary)}.nk-menu-item.danger{color:var(--nk-danger)}.nk-menu-item>.nk-switch{margin-left:auto}.nk-menu-sep{border-top:1px solid var(--nk-border);margin:5px 4px}.nk-menu-label{font-size:12px;color:var(--nk-text-tertiary);padding:5px 8px 2px}.nk-pop.floating{z-index:60;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-4px) scale(.98);transform-origin:top;transition:opacity .15s ease,transform .15s ease,visibility 0s linear .15s}.nk-pop.floating.open{opacity:1;visibility:visible;pointer-events:auto;transform:none;transition:opacity .15s ease,transform .15s ease,visibility 0s}.nk-cmdk-backdrop{position:fixed;inset:0;background:var(--nk-scrim-soft);display:flex;justify-content:center;align-items:flex-start;padding:max(14vh,env(safe-area-inset-top,0px)) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);z-index:110;opacity:0;pointer-events:none;transition:opacity .18s ease}.nk-cmdk-backdrop.open{opacity:1;pointer-events:auto}.nk-cmdk{max-width:100%;width:min(560px,92vw);background:var(--nk-bg);border-radius:12px;box-shadow:var(--nk-shadow-menu);overflow:hidden;transform:scale(.98);transition:transform .18s ease}.nk-cmdk-backdrop.open .nk-cmdk{transform:scale(1)}.nk-cmdk-input-row{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--nk-border)}.nk-cmdk-input-row input{flex:1;border:none;outline:none;background:transparent;font-family:inherit;font-size:16px;color:var(--nk-text)}.nk-cmdk-input-row input::placeholder{color:var(--nk-text-tertiary)}.nk-cmdk-list{max-height:320px;overflow-y:auto;padding:6px}.nk-cmdk-group{font-size:12px;color:var(--nk-text-tertiary);padding:8px 10px 3px}.nk-cmdk-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:14px;user-select:none}.nk-cmdk-item.selected{background:var(--nk-bg-active)}.nk-cmdk-item .m-icon,.nk-cmdk-item ::slotted(.m-icon),.nk-cmdk-item ::slotted([slot=\"icon\"]){width:17px;text-align:center;font-size:14px}.nk-cmdk-item .m-shortcut,.nk-cmdk-item ::slotted(.m-shortcut){margin-left:auto;font-size:12px;color:var(--nk-text-tertiary)}.nk-cmdk-empty{padding:30px;text-align:center;color:var(--nk-text-tertiary);font-size:13.5px}.nk-cmdk-footer{display:flex;gap:14px;padding:8px 16px;border-top:1px solid var(--nk-border);font-size:11.5px;color:var(--nk-text-tertiary)}.nk-sheet-backdrop{position:fixed;inset:0;z-index:100;display:none;flex-direction:column;align-items:center;justify-content:flex-end;padding-top:max(24px,env(safe-area-inset-top,0px));background:var(--nk-scrim-soft);opacity:0;transition:opacity .2s ease,display .25s allow-discrete}.nk-sheet-backdrop.open{display:flex;opacity:1}@starting-style{.nk-sheet-backdrop.open{opacity:0}}.nk-sheet{--_nk-row: 40px;width:100%;max-width:640px;max-height:100%;overflow-y:auto;overscroll-behavior:contain;padding:6px max(10px,env(safe-area-inset-right,0px)) max(16px,env(safe-area-inset-bottom,0px)) max(10px,env(safe-area-inset-left,0px));background:var(--nk-bg);color:var(--nk-text);border-radius:14px 14px 0 0;box-shadow:var(--nk-shadow-menu);translate:0 100%;transition:translate .25s cubic-bezier(.2,.8,.2,1)}.nk-sheet-backdrop.open .nk-sheet{translate:0 0}@starting-style{.nk-sheet-backdrop.open .nk-sheet{translate:0 100%}}.nk-sheet .sh-grabber,.nk-sheet ::slotted(.sh-grabber){width:36px;height:4px;margin:4px auto 10px;border-radius:2px;background:var(--nk-border-strong)}.nk-sheet .sh-title,.nk-sheet ::slotted(.sh-title){font-size:14px;font-weight:600;text-align:center;padding:0 8px 10px}.nk-toast{position:fixed;bottom:max(20px,calc(env(safe-area-inset-bottom,0px) + 12px));left:50%;transform:translate(-50%) translateY(80px);z-index:120;width:max-content;max-width:calc(100% - 32px);background:var(--nk-text);color:var(--nk-bg);padding:8px 16px;border-radius:8px;font-size:14px;opacity:0;transition:all .3s ease;pointer-events:none;box-shadow:var(--nk-shadow-menu);display:flex;gap:8px;align-items:center}.nk-toast.show{opacity:1;transform:translate(-50%) translateY(0)}.nk-gallery-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:20px 32px;margin:12px 0}.nk-g-item>h4{font-size:12px;font-weight:500;color:var(--nk-text-tertiary);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}.nk-g-item ::slotted(h4){font-size:12px;font-weight:500;color:var(--nk-text-tertiary);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px!important}.nk-tabs{display:flex;gap:2px;border-bottom:1px solid var(--nk-border);font-size:14px}.nk-tab{padding:7px 11px;cursor:pointer;color:var(--nk-text-secondary);border-bottom:2px solid transparent;margin-bottom:-1px;user-select:none}.nk-tab:hover{color:var(--nk-text)}.nk-tab.active{color:var(--nk-text);border-bottom-color:var(--nk-text);font-weight:500}.nk-tab-panel{padding:12px 2px;color:var(--nk-text-secondary);line-height:1.55;font-size:14px}.nk-template-btn{display:flex;align-items:center;gap:8px;width:100%;font-family:inherit;font-size:14px;color:var(--nk-text-secondary);background:var(--nk-bg-callout);border:none;border-radius:var(--nk-radius);padding:8px 12px;cursor:pointer;margin-bottom:6px;text-align:left}.nk-template-btn:hover{background:var(--nk-bg-hover)}.nk-stats{display:flex;gap:10px}.nk-stat{flex:1;border:1px solid var(--nk-border);border-radius:8px;padding:12px 14px}.nk-stat .s-label,.nk-stat ::slotted(.s-label),.nk-stat ::slotted([slot=\"label\"]){font-size:12px;color:var(--nk-text-secondary);margin-bottom:4px}.nk-stat .s-value,.nk-stat ::slotted(.s-value),.nk-stat ::slotted([slot=\"value\"]){font-size:22px;font-weight:600;letter-spacing:-.01em}.nk-stat .s-delta,.nk-stat ::slotted(.s-delta),.nk-stat ::slotted([slot=\"delta\"]){font-size:12px;margin-top:3px}.nk-stat .s-delta.up,.nk-stat ::slotted(.s-delta.up),.nk-stat ::slotted([slot=\"delta\"].up){color:var(--nk-color-green)}.nk-stat .s-delta.down,.nk-stat ::slotted(.s-delta.down),.nk-stat ::slotted([slot=\"delta\"].down){color:var(--nk-danger)}.nk-synced{border:1.5px solid color-mix(in srgb,var(--nk-danger) 55%,transparent);border-radius:8px;padding:12px 14px;position:relative;margin:8px 0}.nk-synced .synced-badge{position:absolute;top:-9px;right:10px;font-size:11px;background:var(--nk-danger);color:var(--nk-on-accent);border-radius:8px;padding:1px 8px}.nk-segmented{display:inline-flex;background:var(--nk-bg-callout);border-radius:7px;padding:2px}.nk-segmented button{font-family:inherit;font-size:14px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 12px;border-radius:5px;cursor:pointer}.nk-segmented ::slotted(button){font-family:inherit;font-size:14px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 12px!important;border-radius:5px;cursor:pointer}.nk-segmented button.active,.nk-segmented ::slotted(button.active){background:var(--nk-bg);color:var(--nk-text);font-weight:500;box-shadow:var(--nk-shadow-segment)}.nk-segmented.wrap{flex-wrap:wrap}.nk-segmented.scroll{max-width:100%;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}.nk-segmented.scroll::-webkit-scrollbar{display:none}.nk-segmented.scroll button,.nk-segmented.scroll ::slotted(button){flex-shrink:0;white-space:nowrap}.nk-banner{display:flex;align-items:center;gap:10px;font-size:14px;border-radius:8px;padding:10px 14px;margin-bottom:8px;color:var(--nk-text)}.nk-banner.info{background:var(--nk-tint-blue)}.nk-banner.success{background:var(--nk-tint-green)}.nk-banner.warning{background:var(--nk-tint-yellow)}.nk-banner.danger{background:var(--nk-tint-red)}.nk-banner .b-action,.nk-banner ::slotted(.b-action),.nk-banner ::slotted([slot=\"action\"]){margin-left:auto;font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px}.nk-avatar-group{display:flex}.nk-avatar-group .mini-avatar,.nk-avatar-group .nk-avatar,.nk-avatar-group ::slotted(.mini-avatar),.nk-avatar-group ::slotted(.nk-avatar){width:26px;height:26px;border-radius:50%;color:var(--nk-on-accent);font-size:10.5px;font-weight:600;border:2px solid var(--nk-bg);display:flex;align-items:center;justify-content:center;margin-left:-7px}.nk-avatar-group .mini-avatar:first-child,.nk-avatar-group .nk-avatar:first-child,.nk-avatar-group ::slotted(.mini-avatar:first-child),.nk-avatar-group ::slotted(.nk-avatar:first-child){margin-left:0}.nk-avatar-group .more,.nk-avatar-group ::slotted(.more){background:var(--nk-bg-callout);color:var(--nk-text-secondary)}.nk-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;height:24px;border-radius:50%;overflow:hidden;vertical-align:middle;font-size:10px;font-weight:600;line-height:1;color:var(--nk-on-accent);user-select:none;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));object-fit:cover}.nk-avatar.small{width:20px;height:20px;font-size:9px}.nk-avatar.large{width:32px;height:32px;font-size:12px}.nk-avatar.xlarge{width:56px;height:56px;font-size:20px}.nk-avatar.square{border-radius:4px}.nk-avatar>img,.nk-avatar ::slotted(img){display:block;width:100%;height:100%;object-fit:cover}.nk-avatar.gray{background:var(--nk-color-gray)}.nk-avatar.brown{background:var(--nk-color-brown)}.nk-avatar.orange{background:var(--nk-color-orange)}.nk-avatar.yellow{background:var(--nk-color-yellow)}.nk-avatar.green{background:var(--nk-color-green)}.nk-avatar.blue{background:var(--nk-color-blue)}.nk-avatar.purple{background:var(--nk-color-purple)}.nk-avatar.pink{background:var(--nk-color-pink)}.nk-avatar.red{background:var(--nk-color-red)}.nk-panels{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:12px;margin:12px 0}.nk-panel{display:flex;flex-direction:column;gap:6px;min-width:0;padding:14px 16px;border:1px solid var(--nk-border);border-radius:10px;background:var(--nk-bg-card);box-shadow:var(--nk-shadow-card);font-size:14px;line-height:1.5;color:inherit;text-decoration:none;text-align:left}:is(a,button).nk-panel{cursor:pointer;font-family:inherit;transition:border-color .15s,background .15s}:is(a,button).nk-panel:hover{border-color:var(--nk-border-strong)}.nk-panel>h3{font-size:14px;font-weight:600;line-height:1.4}.nk-panel ::slotted(h3){font-size:14px;font-weight:600;line-height:1.4;margin:0!important}.nk-panel>p{font-size:13px;color:var(--nk-text-secondary)}.nk-panel ::slotted(p){font-size:13px;color:var(--nk-text-secondary);margin:0!important}.nk-panel>.nk-cover{flex:none;height:64px;margin:-14px -16px 2px;border-radius:9px 9px 0 0}.nk-panel>.nk-page-icon{font-size:28px}.nk-panel>.nk-cover+.nk-page-icon{margin-top:-24px}.nk-skeleton{border-radius:5px;margin-bottom:10px;background:linear-gradient(90deg,var(--nk-bg-callout) 25%,var(--nk-bg-hover) 50%,var(--nk-bg-callout) 75%);background-size:200% 100%;animation:nk-shimmer 1.6s infinite}@keyframes nk-shimmer{to{background-position:-200% 0}}.nk-empty{text-align:center;padding:36px 20px;border:1.5px dashed var(--nk-border-strong);border-radius:10px;color:var(--nk-text-tertiary)}.nk-empty .e-icon,.nk-empty ::slotted(.e-icon),.nk-empty ::slotted([slot=\"icon\"]){font-size:30px;margin-bottom:8px}.nk-empty .e-title,.nk-empty ::slotted(.e-title),.nk-empty ::slotted([slot=\"title\"]){font-weight:500;color:var(--nk-text-secondary);margin-bottom:3px;font-size:14px}.nk-empty .e-desc,.nk-empty ::slotted(.e-desc),.nk-empty ::slotted([slot=\"desc\"]){font-size:13px;margin-bottom:12px}.nk-empty .e-actions,.nk-empty ::slotted(.e-actions){display:flex;flex-wrap:wrap;justify-content:center;gap:8px}.nk-steps{display:flex;flex-direction:column;margin:8px 0;padding:0;list-style:none;font-size:14px}.nk-step{position:relative;display:flex;align-items:flex-start;gap:10px;padding-bottom:14px;line-height:20px;color:var(--nk-text-tertiary)}.nk-step:last-child{padding-bottom:0}.nk-step:not(:last-child):after{content:\"\";position:absolute;left:10px;top:24px;bottom:4px;width:1px;background:var(--nk-border)}.nk-step .st-mark{flex:none;width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--nk-border-strong);background:var(--nk-bg);font-size:11px;font-weight:600;line-height:1}.nk-step .st-desc{display:block;font-size:12px;line-height:18px;color:var(--nk-text-tertiary);font-weight:400}.nk-step.done{color:var(--nk-text-secondary)}.nk-step.done .st-mark{background:var(--nk-tag-green-bg);color:var(--nk-tag-green-text);border-color:transparent}.nk-step.current{color:var(--nk-text);font-weight:500}.nk-step.current .st-mark{border-color:var(--nk-accent);color:var(--nk-accent)}.nk-comments{border-left:1px solid var(--nk-border);padding:4px 0 4px 18px;margin:8px 0 8px 8px}.nk-comment{display:flex;gap:9px;margin-bottom:14px}.nk-comment .mini-avatar,.nk-comment ::slotted(.mini-avatar),.nk-comment ::slotted([slot=\"avatar\"]){width:24px;height:24px;border-radius:50%;color:var(--nk-on-accent);flex-shrink:0;font-size:10px;font-weight:600;display:flex;align-items:center;justify-content:center}.nk-comment .c-head,.nk-comment ::slotted(.c-head){font-size:12px;color:var(--nk-text-tertiary);margin-bottom:2px}.nk-comment .c-head b{color:var(--nk-text);font-weight:600}.nk-comment .c-body,.nk-comment ::slotted(.c-body){font-size:14px;line-height:1.5}.nk-comment-input{display:flex;gap:8px;align-items:center;margin-top:4px}.nk-comment-input input{min-width:0;flex:1}.nk-ai-thread{display:flex;flex-direction:column;gap:14px}.nk-ai-msg{display:flex;gap:9px}.nk-ai-msg .mini-avatar,.nk-ai-msg ::slotted(.mini-avatar),.nk-ai-msg ::slotted([slot=\"avatar\"]){width:24px;height:24px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:12px;background:var(--nk-bg-callout)}.nk-ai-msg.user .mini-avatar,.nk-ai-msg.user ::slotted(.mini-avatar),.nk-ai-msg.user ::slotted([slot=\"avatar\"]){background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:9.5px;font-weight:600}.nk-ai-msg .a-body,.nk-ai-msg ::slotted(.a-body){font-size:14px;line-height:1.55;padding-top:2px}.nk-ai-msg .a-name,.nk-ai-msg ::slotted(.a-name){font-size:12px;font-weight:600;margin-bottom:2px}.nk-ai-msg .a-name span{color:var(--nk-text-tertiary);font-weight:400}.nk-ai-msg.user.bubble{justify-content:flex-end}.nk-ai-msg.bubble .a-body,.nk-ai-msg.bubble ::slotted(.a-body){max-width:85%;padding:6px 12px;border-radius:16px;background:var(--nk-bg-callout)}.nk-ai-actions{display:flex;gap:4px;margin-top:6px}.nk-ai-actions button{font-family:inherit;font-size:12px;color:var(--nk-text-secondary);background:transparent;border:1px solid var(--nk-border);border-radius:5px;padding:2px 8px;cursor:pointer}.nk-ai-actions ::slotted(button){font-family:inherit;font-size:12px;color:var(--nk-text-secondary);background:transparent;border:1px solid var(--nk-border);border-radius:5px;padding:2px 8px!important;cursor:pointer}.nk-ai-actions button:hover,.nk-ai-actions ::slotted(button:hover){background:var(--nk-bg-hover);color:var(--nk-text)}.nk-ai-input-row{display:flex;align-items:center;gap:8px;margin-top:14px;border:1px solid var(--nk-border-strong);border-radius:10px;padding:8px 12px}.nk-ai-input-row:focus-within{border-color:var(--nk-accent)}.nk-ai-input-row input{flex:1;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;color:var(--nk-text);min-width:0}.nk-ai-input-row input::placeholder{color:var(--nk-text-tertiary)}.nk-ai-send{border:none;background:var(--nk-accent);color:var(--nk-on-accent);border-radius:6px;width:26px;height:26px;cursor:pointer;font-size:13px;flex-shrink:0}.nk-block-host{position:relative;border-radius:var(--nk-radius);margin:8px 0;padding:2px 0 2px 2px;transition:background .15s,box-shadow .15s}.nk-block-host:hover{background:var(--nk-bg-hover)}.nk-block-host:focus-within{background:transparent;box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 25%,transparent)}.nk-block-host.nk-drop-target{box-shadow:0 -2px 0 0 var(--nk-accent);background:transparent}.nk-block-host .nk-block-handle,.nk-block-host ::slotted(.nk-block-handle){position:absolute;left:-26px;top:4px;width:18px;height:20px;border-radius:4px;display:flex;align-items:center;justify-content:center;color:var(--nk-text-tertiary);font-size:13px;cursor:grab;opacity:0;transition:opacity .15s;user-select:none}.nk-block-host:hover .nk-block-handle{opacity:1}.nk-block-host .nk-block-actions{position:absolute;display:flex;gap:1px;z-index:2;opacity:0;transition:opacity .15s;pointer-events:none}.nk-block-host .nk-block-actions.show{opacity:1;pointer-events:auto}.nk-block-host .nk-block-actions button,.nk-block-host .nk-block-actions ::slotted(button){width:20px;height:22px;padding:0;border:none;border-radius:4px;background:transparent;color:var(--nk-text-tertiary);font-family:inherit;font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}.nk-block-host .nk-block-actions button:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-block-host .nk-block-actions .drag{cursor:grab}.nk-block-host .nk-block-actions .drag:active{cursor:grabbing}.nk-prose,.nk-block-host .ProseMirror{font-family:var(--nk-font);line-height:1.5;color:var(--nk-text);overflow-wrap:break-word}.nk-block-host .ProseMirror{outline:none;min-height:60px;padding:4px 2px}.nk-prose>*+*,.nk-block-host .ProseMirror>*+*{margin-top:6px}.nk-prose h1,.nk-block-host .ProseMirror h1{font-size:1.875em;font-weight:600;line-height:1.3;letter-spacing:-.01em;margin:32px 0 4px}.nk-prose h2,.nk-block-host .ProseMirror h2{font-size:1.5em;font-weight:600;line-height:1.3;margin:24px 0 4px}.nk-prose h3,.nk-block-host .ProseMirror h3{font-size:1.25em;font-weight:600;line-height:1.3;margin:16px 0 2px}.nk-prose :is(h4,h5,h6),.nk-block-host .ProseMirror :is(h4,h5,h6){font-size:1em;font-weight:600;margin:12px 0 0}.nk-prose>:first-child,.nk-block-host .ProseMirror>:first-child{margin-top:0}.nk-prose>:last-child,.nk-block-host .ProseMirror>:last-child{margin-bottom:0}.nk-prose p:empty:before{content:\"\";display:inline-block}.nk-prose :is(strong,b),.nk-block-host .ProseMirror :is(strong,b){font-weight:600}.nk-prose :is(ul,ol),.nk-block-host .ProseMirror :is(ul,ol){padding-left:24px;margin:4px 0}.nk-prose ul,.nk-block-host .ProseMirror ul{list-style:disc}.nk-prose ol,.nk-block-host .ProseMirror ol{list-style:decimal}.nk-prose li,.nk-block-host .ProseMirror li{margin:2px 0}.nk-prose li::marker,.nk-block-host .ProseMirror li::marker{color:var(--nk-text-tertiary)}.nk-prose ul[data-type=taskList],.nk-block-host .ProseMirror ul[data-type=taskList]{list-style:none;padding-left:2px}.nk-prose ul[data-type=taskList] li,.nk-block-host .ProseMirror ul[data-type=taskList] li{display:flex;gap:8px;align-items:flex-start}.nk-prose ul[data-type=taskList] li>label,.nk-block-host .ProseMirror ul[data-type=taskList] li>label{flex-shrink:0;margin-top:max(0px,calc((1lh - 16px)/2));user-select:none}.nk-prose ul[data-type=taskList] li>div,.nk-block-host .ProseMirror ul[data-type=taskList] li>div{flex:1;min-width:0}.nk-prose ul[data-type=taskList] input[type=checkbox],.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]{appearance:none;width:16px;height:16px;margin:0;border:1.4px solid var(--nk-border-strong);border-radius:2px;cursor:pointer;position:relative;background:var(--nk-bg);display:block}.nk-prose ul[data-type=taskList] input[type=checkbox]:checked,.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-prose ul[data-type=taskList] input[type=checkbox]:checked:after,.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:11px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-prose li[data-checked=true]>div,.nk-block-host .ProseMirror li[data-checked=true]>div{text-decoration:line-through;color:var(--nk-text-tertiary)}.nk-prose blockquote,.nk-block-host .ProseMirror blockquote{border-left:3px solid var(--nk-text);padding:2px 0 2px 14px;margin:12px 0;color:var(--nk-text-secondary)}.nk-prose code,.nk-block-host .ProseMirror code{font-family:var(--nk-font-mono);font-size:85%;color:var(--nk-danger);background:color-mix(in srgb,var(--nk-danger) 8%,transparent);border-radius:4px;padding:1px 5px}.nk-prose pre,.nk-block-host .ProseMirror pre{background:var(--nk-bg-code);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:16px 20px;margin:12px 0;font-family:var(--nk-font-mono);font-size:13px;line-height:1.6;color:var(--nk-text-secondary);overflow-x:auto}.nk-prose pre code,.nk-block-host .ProseMirror pre code{background:none;color:inherit;padding:0;font-size:inherit}.nk-prose hr,.nk-block-host .ProseMirror hr{border:none;border-top:1px solid var(--nk-border);margin:20px 0}.nk-prose a,.nk-block-host .ProseMirror a{color:var(--nk-accent);text-decoration:underline;text-underline-offset:2px}.nk-prose img{max-width:100%;height:auto}.nk-prose table{display:block;width:max-content;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:14px;margin:12px 0}.nk-prose :is(th,td){padding:6px 10px;border:1px solid var(--nk-border);text-align:left;vertical-align:top}.nk-prose th{font-weight:600}.nk-block-host .ProseMirror-gapcursor:after{border-top-color:var(--nk-text)}.nk-block-host .ProseMirror .ProseMirror-selectednode{background:color-mix(in srgb,var(--nk-accent) 8%,transparent)}.nk-block-host .ProseMirror-selectednode{box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 35%,transparent);border-radius:3px}.nk-block-host .ProseMirror ::selection{background:color-mix(in srgb,var(--nk-accent) 25%,transparent)}.nk-block-host .ProseMirror p.is-editor-empty:first-child:before,.nk-block-host .ProseMirror .is-empty:before{content:attr(data-placeholder);color:var(--nk-text-tertiary);float:left;height:0;pointer-events:none}.nk-block-host .bn-container{font-family:var(--nk-font);color:var(--nk-text);background:transparent}.nk-block-host .bn-editor{padding:4px 2px}.nk-block-host .bn-block-content{font-size:14px;line-height:1.6}.nk-block-host .bn-side-menu{color:var(--nk-text-tertiary)}.nk-block-host .bn-drag-handle{border-radius:4px}.nk-block-host .bn-drag-handle:hover{background:var(--nk-bg-hover)}.nk-block-host .novel-editor{font-family:var(--nk-font);color:var(--nk-text)}.nk-block-host .novel-prose{max-width:none}.nk-slash-menu,.nk-block-host .bn-suggestion-menu,.nk-block-host .tippy-box{background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);padding:6px;width:280px;max-height:320px;overflow-y:auto;font-family:var(--nk-font);font-size:14px;color:var(--nk-text)}.nk-slash-menu-label{font-size:12px;color:var(--nk-text-tertiary);padding:6px 9px 2px}.nk-slash-item{display:flex;align-items:center;gap:10px;padding:6px 9px;border-radius:5px;cursor:pointer;user-select:none}.nk-slash-item:hover,.nk-slash-item.selected{background:var(--nk-bg-hover)}.nk-slash-item .m-icon,.nk-slash-item ::slotted(.m-icon){width:28px;height:28px;flex-shrink:0;border-radius:4px;background:var(--nk-bg-callout);border:1px solid var(--nk-border);display:flex;align-items:center;justify-content:center;font-size:15px}.nk-slash-item .m-desc{font-size:12px;color:var(--nk-text-tertiary)}.nk-bubble-menu{display:flex;align-items:center;gap:2px;background:var(--nk-bg);border-radius:8px;box-shadow:var(--nk-shadow-menu);padding:4px}.nk-bubble-menu button{font-family:inherit;font-size:13px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 8px;border-radius:5px;cursor:pointer}.nk-bubble-menu ::slotted(button){font-family:inherit;font-size:13px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 8px!important;border-radius:5px;cursor:pointer}.nk-bubble-menu button:hover,.nk-bubble-menu ::slotted(button:hover){background:var(--nk-bg-hover);color:var(--nk-text)}.nk-bubble-menu button.active,.nk-bubble-menu ::slotted(button.active){color:var(--nk-accent)}@media(max-width:860px){.nk-sidebar{display:none;position:fixed;inset:0 auto 0 0;z-index:60;transform:translate(-100%);transition:background .25s ease,transform .24s cubic-bezier(.2,.8,.25,1),display .24s allow-discrete}.nk-sidebar.open{display:flex;transform:none}@starting-style{.nk-sidebar.open{transform:translate(-100%)}}.nk-sidebar-backdrop{opacity:0;transition:opacity .24s ease,display .24s allow-discrete}.nk-sidebar-backdrop.open{display:block;opacity:1}@starting-style{.nk-sidebar-backdrop.open{opacity:0}}.nk-sidebar-toggle{display:inline-flex}.nk-tab-bar{display:flex}.nk-tab-bar.fixed+.nk-tab-bar-spacer{display:block}.nk-page{padding-left:max(24px,env(safe-area-inset-left,0px));padding-right:max(24px,env(safe-area-inset-right,0px));padding-bottom:80px}.nk-settings-nav{width:60px;min-width:60px}.nk-settings-nav .label,.nk-settings-nav .nk-section-label,.nk-settings-user .u-text{display:none}.nk-settings-content{padding:24px}.nk-cmdk-backdrop{padding-top:max(6vh,env(safe-area-inset-top,0px))}.nk-cmdk{width:min(560px,96vw)}.nk-stats{flex-wrap:wrap}.nk-breadcrumb{min-width:0}.nk-breadcrumb>.crumb:not(:last-child),.nk-breadcrumb ::slotted(.crumb:not(:last-child)),.nk-breadcrumb>.sep,.nk-breadcrumb ::slotted(.sep),.nk-topbar-meta,.nk-topbar-actions ::slotted(.nk-topbar-meta){display:none}.nk-breadcrumb>.crumb:last-child,.nk-breadcrumb ::slotted(.crumb:last-child){display:block;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-topbar-actions{flex-shrink:0}.nk-field{flex-wrap:wrap;row-gap:6px}.nk-field .f-control,.nk-field ::slotted(.f-control){max-width:100%;min-width:0}.nk-input,.nk-select,.nk-textarea,.nk-slider{max-width:100%}.nk-prop{flex-direction:column;align-items:stretch}.nk-prop .p-name{flex:none;min-height:26px}.nk-prop .p-value{min-height:30px;padding:3px 6px 7px}.nk-pop.sheet{position:fixed!important;inset:auto 0 0!important;width:auto!important;transform:none!important;z-index:100;--_nk-row: 40px;max-height:85dvh;overflow-y:auto;overscroll-behavior:contain;border-radius:14px 14px 0 0;padding:6px max(8px,env(safe-area-inset-right,0px)) max(12px,env(safe-area-inset-bottom,0px)) max(8px,env(safe-area-inset-left,0px));box-shadow:0 0 0 100vmax var(--nk-scrim-soft),var(--nk-shadow-menu)}.nk-pop.sheet:before{content:\"\";display:block;width:36px;height:4px;margin:4px auto 8px;border-radius:2px;background:var(--nk-border-strong)}.nk-pop.sheet.floating{translate:0 100%;transition:opacity .2s ease,translate .25s cubic-bezier(.2,.8,.2,1),visibility 0s linear .25s}.nk-pop.sheet.floating.open{translate:0 0;transition:opacity .2s ease,translate .25s cubic-bezier(.2,.8,.2,1),visibility 0s}:root:has(.nk-tab-bar:not([hidden])) .nk-toast{bottom:calc(var(--nk-tab-bar-height) + max(6px,env(safe-area-inset-bottom,0px)) + 6px)}:root:has(.nk-tab-bar.floating:not([hidden])) .nk-toast{bottom:calc(var(--nk-tab-bar-height) + 24px + env(safe-area-inset-bottom,0px))}}@media(prefers-reduced-motion:reduce){.nk-skeleton{animation:none;background:var(--nk-bg-callout)}[class*=nk-],[class*=nk-]:before,[class*=nk-]:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}\n/*# sourceMappingURL=notionkit.min.css.map */\n";
|
|
9
|
+
const componentsTail = ".nk-body{margin:0;min-height:100vh;min-height:100dvh;font-family:var(--nk-font);font-size:14px;background:var(--nk-bg);color:var(--nk-text);-webkit-font-smoothing:auto;transition:background .25s ease,color .25s ease}.nk-app{display:flex;height:100vh;height:100dvh;overflow:hidden}.nk-sidebar{width:calc(var(--nk-sidebar-width) + env(safe-area-inset-left,0px));min-width:calc(var(--nk-sidebar-width) + env(safe-area-inset-left,0px));padding-left:env(safe-area-inset-left,0px);background:var(--nk-bg-sidebar);display:flex;flex-direction:column;border-right:1px solid var(--nk-border);transition:background .25s ease}.nk-workspace{display:flex;align-items:center;gap:8px;padding:10px 12px;margin:6px 8px 2px;border-radius:var(--nk-radius);cursor:pointer;font-weight:500;user-select:none}.nk-workspace:hover{background:var(--nk-bg-hover)}.nk-workspace .avatar,.nk-workspace ::slotted(.avatar),.nk-workspace ::slotted([slot=\"avatar\"]){width:22px;height:22px;border-radius:4px;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center}.nk-workspace .chev{margin-left:auto;color:var(--nk-text-tertiary);font-size:11px}.nk-sidebar-scroll{flex:1;overflow-y:auto;padding:4px 8px 16px}.nk-sidebar-scroll::-webkit-scrollbar{width:8px}.nk-sidebar-scroll::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:4px}.nk-section-label{font-size:12px;font-weight:500;letter-spacing:.01em;color:var(--nk-text-tertiary);padding:14px 10px 4px;display:flex;justify-content:space-between;align-items:center}.nk-section-label .plus{cursor:pointer;border-radius:4px;padding:0 4px;font-size:13px;opacity:0;transition:opacity .15s}.nk-section-label:hover .plus{opacity:1}.nk-section-label .plus:hover{background:var(--nk-bg-hover)}.nk-sidebar-footer{padding:8px;border-top:1px solid var(--nk-border);color:var(--nk-text-sidebar);font-size:14px}.nk-sidebar-footer .nk-tree-item{min-height:26px}.nk-sidebar-backdrop{display:none;position:fixed;inset:0;z-index:59;background:var(--nk-scrim-soft)}.nk-sidebar-toggle{display:none}.nk-main{flex:1;display:flex;flex-direction:column;min-width:0}.nk-topbar{height:44px;display:flex;align-items:center;padding:0 max(12px,env(safe-area-inset-right,0px)) 0 max(12px,env(safe-area-inset-left,0px));gap:8px;flex-shrink:0}.nk-breadcrumb{display:flex;align-items:center;gap:4px;font-size:14px}.nk-breadcrumb .crumb,.nk-breadcrumb ::slotted(.crumb){padding:2px 6px;border-radius:4px;cursor:pointer;color:var(--nk-text-sidebar);display:flex;align-items:center;gap:5px}.nk-breadcrumb .crumb:hover{background:var(--nk-bg-hover)}a.crumb{text-decoration:none}.nk-breadcrumb .crumb.current,.nk-breadcrumb ::slotted(.crumb.current){color:var(--nk-text)}.nk-breadcrumb .sep{color:var(--nk-text-tertiary);font-size:12px}.nk-topbar-actions{margin-left:auto;display:flex;align-items:center;gap:4px}.nk-topbar-btn{padding:4px 8px;border-radius:var(--nk-radius);cursor:pointer;color:var(--nk-text-sidebar);font-size:14px;user-select:none;border:none;background:transparent;font-family:inherit}.nk-topbar-btn:hover{background:var(--nk-bg-hover)}.nk-topbar-btn svg,.nk-topbar-btn ::slotted(svg){width:16px;height:16px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.nk-share-btn{font-size:14px;padding:4px 8px}.nk-topbar-meta,.nk-topbar-actions ::slotted(.nk-topbar-meta){padding:4px 8px;font-size:12px;color:var(--nk-text-tertiary);white-space:nowrap}.nk-theme-toggle{font-size:15px;width:30px;height:28px;padding:0}.nk-tab-bar{display:none;flex:none;align-items:stretch;gap:2px;position:sticky;bottom:0;z-index:30;box-sizing:border-box;height:calc(var(--nk-tab-bar-height) - 6px + max(6px,env(safe-area-inset-bottom,0px)));padding:6px max(4px,env(safe-area-inset-right,0px)) max(6px,env(safe-area-inset-bottom,0px)) max(4px,env(safe-area-inset-left,0px));background:var(--nk-bg-sidebar);border-top:1px solid var(--nk-border)}.nk-tab-bar.always{display:flex}.nk-tab-bar.fixed{position:fixed;left:0;right:0;bottom:0}.nk-tab-bar-spacer{display:none;flex:none;height:calc(var(--nk-tab-bar-height) - 6px + max(6px,env(safe-area-inset-bottom,0px)))}.nk-tab-bar.always.fixed+.nk-tab-bar-spacer{display:block}.nk-tab-bar.floating{position:fixed;left:max(12px,env(safe-area-inset-left,0px));right:max(12px,env(safe-area-inset-right,0px));bottom:calc(12px + env(safe-area-inset-bottom,0px));height:var(--nk-tab-bar-height);padding:6px;border:1px solid var(--nk-border);border-radius:16px;box-shadow:var(--nk-shadow-menu)}.nk-tab-bar-item{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;padding:4px 2px;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:10.5px;line-height:1.2;color:var(--nk-text-secondary);text-decoration:none;cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent}.nk-tab-bar-item:hover{color:var(--nk-text);background:var(--nk-bg-hover)}.nk-tab-bar-item.active{color:var(--nk-accent)}.nk-tab-bar-item:disabled{opacity:.5;cursor:not-allowed}.nk-tab-bar-item .icon,.nk-tab-bar-item ::slotted([slot=\"icon\"]){font-size:20px;line-height:1}.nk-tab-bar-item .label,.nk-tab-bar-item ::slotted(.label){max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nk-tree-item{display:flex;align-items:center;gap:6px;padding:3px 8px 3px 10px;border-radius:var(--nk-radius);cursor:pointer;user-select:none;color:var(--nk-text-sidebar);position:relative;min-height:var(--_nk-row, 28px)}.nk-tree-item:hover{background:var(--nk-bg-hover)}.nk-tree-item.active{background:var(--nk-bg-active);color:var(--nk-text);font-weight:500}.nk-tree-item.compact{min-height:26px}.nk-tree-item .icon,.nk-tree-item ::slotted(.icon),.nk-tree-item ::slotted([slot=\"icon\"]){font-size:15px;width:20px;text-align:center;flex-shrink:0}.nk-tree-item .label,.nk-tree-item ::slotted(.label){white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-tree-item .actions{margin-left:auto;display:none;gap:2px;color:var(--nk-text-tertiary)}.nk-tree-item:hover .actions{display:flex}.nk-tree-item .actions span{padding:0 3px;border-radius:3px;font-size:12px}.nk-tree-item .actions span:hover{background:var(--nk-bg-active)}.nk-tree-children{margin-left:14px;border-left:1px solid var(--nk-border);padding-left:4px;overflow:hidden}.nk-tree-children.collapsed{display:none}.nk-toggle-arrow{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:9px;color:var(--nk-text-tertiary);border-radius:3px;transition:transform .15s}.nk-toggle-arrow.open{transform:rotate(90deg)}.nk-kbd-hint{margin-left:auto;display:flex;gap:3px;align-items:center}.nk-kbd{font-family:inherit;font-size:10.5px;background:var(--nk-bg-callout);border:1px solid var(--nk-border-strong);border-bottom-width:2px;border-radius:4px;padding:0 4px}.nk-page-scroll{flex:1;overflow-y:auto}.nk-page-scroll::-webkit-scrollbar{width:10px}.nk-page-scroll::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:5px;border:2px solid var(--nk-bg)}.nk-cover{height:200px;background:radial-gradient(ellipse at 20% 40%,color-mix(in srgb,var(--nk-decor-purple) 35%,transparent),transparent 55%),radial-gradient(ellipse at 80% 20%,color-mix(in srgb,var(--nk-decor-blue) 35%,transparent),transparent 55%),radial-gradient(ellipse at 60% 90%,color-mix(in srgb,var(--nk-decor-orange) 25%,transparent),transparent 55%),var(--nk-bg-callout)}.nk-cover>img,.nk-cover ::slotted(img){display:block;width:100%;height:100%;object-fit:cover}.nk-page{max-width:760px;margin:0 auto;padding:24px max(64px,env(safe-area-inset-right,0px)) 120px max(64px,env(safe-area-inset-left,0px));font-size:16px;line-height:1.5}.nk-page.full{max-width:none}.nk-page.small{font-size:14px}.nk-cover+.nk-page,.nk-page.covered{padding-top:0}.nk-page-icon,.nk-page ::slotted(.nk-page-icon),.nk-page ::slotted([slot=\"icon\"]){font-size:64px;line-height:1;margin-top:0;cursor:pointer;user-select:none;display:inline-block}.nk-cover+.nk-page .nk-page-icon,.nk-cover+.nk-page ::slotted(.nk-page-icon),.nk-cover+.nk-page ::slotted([slot=\"icon\"]),.nk-page.covered .nk-page-icon,.nk-page.covered ::slotted(.nk-page-icon),.nk-page.covered ::slotted([slot=\"icon\"]){margin-top:-42px}.nk-page-title{font-size:var(--_nk-title, 40px);font-weight:700;line-height:1.2;margin:8px 0 4px;outline:none;letter-spacing:0}.nk-page-meta{color:var(--nk-text-tertiary);font-size:13px;margin-bottom:24px;display:flex;gap:16px}.nk-props{display:flex;flex-direction:column;margin:0 0 20px;font-size:14px;line-height:1.5}.nk-prop{display:flex;align-items:flex-start;min-width:0}.nk-prop .p-name{flex:0 0 160px;min-width:0;min-height:34px;padding:0 6px;display:flex;align-items:center;gap:6px;overflow:hidden;border-radius:var(--nk-radius);color:var(--nk-text-secondary);white-space:nowrap;user-select:none}.nk-prop .p-icon,.nk-prop ::slotted([slot=\"icon\"]){width:16px;flex-shrink:0;text-align:center;font-size:13px}.nk-prop .p-value{flex:1 1 auto;min-width:0;min-height:34px;padding:5px 8px;display:flex;align-items:center;flex-wrap:wrap;gap:4px 6px;border-radius:var(--nk-radius);overflow-wrap:anywhere}.nk-prop .p-name:hover,.nk-prop .p-value:hover{background:var(--nk-bg-hover)}.nk-page p.lead{font-size:1em;line-height:1.6;color:var(--nk-text-secondary);margin-bottom:20px}.nk-page ::slotted(p.lead){font-size:1em;line-height:1.6;color:var(--nk-text-secondary);margin-bottom:20px!important}.nk-heading{font-size:1.5em;font-weight:600;line-height:1.3;margin:32px 0 10px;display:flex;align-items:center;gap:8px}.nk-callout{display:flex;gap:10px;align-items:flex-start;background:var(--nk-bg-callout);border-radius:var(--nk-radius);padding:16px 16px 16px 12px;margin:16px 0;line-height:1.5}.nk-callout .c-icon,.nk-callout ::slotted(.c-icon),.nk-callout ::slotted([slot=\"icon\"]){font-size:17px}.nk-bookmark{display:flex;min-width:0;margin:8px 0;overflow:hidden;border:1px solid var(--nk-border);border-radius:var(--nk-radius);color:var(--nk-text);text-decoration:none;transition:background .12s ease}.nk-bookmark:hover{background:var(--nk-bg-hover)}.nk-bookmark .bm-text{flex:1 1 0;min-width:0;padding:12px 14px 14px;font-size:14px;line-height:20px}.nk-bookmark .bm-title{display:block;min-height:24px;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nk-bookmark .bm-desc{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;max-height:32px;font-size:12px;line-height:16px;color:var(--nk-text-secondary)}.nk-bookmark .bm-url{display:flex;align-items:center;gap:6px;margin-top:6px;font-size:12px;line-height:16px;white-space:nowrap}.nk-bookmark .bm-url>span{min-width:0;overflow:hidden;text-overflow:ellipsis}.nk-bookmark .bm-favicon{flex:none;width:16px;height:16px}.nk-bookmark .bm-cover{position:relative;flex:0 0 33%;max-width:240px}.nk-bookmark .bm-cover>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.nk-todo{display:flex;align-items:flex-start;gap:8px;padding:4px 0}.nk-todo input[type=checkbox]{appearance:none;width:16px;height:16px;margin-top:3px;border:1.4px solid var(--nk-border-strong);border-radius:2px;cursor:pointer;flex-shrink:0;position:relative;background:var(--nk-bg)}.nk-todo input[type=checkbox]:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-todo input[type=checkbox]:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:11px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-todo input:checked+span{text-decoration:line-through;color:var(--nk-text-tertiary)}.nk-todo input:disabled{opacity:.5;cursor:not-allowed}.nk-toggle{margin:6px 0}.nk-toggle summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:var(--nk-radius);font-weight:500;user-select:none}.nk-toggle summary::-webkit-details-marker{display:none}.nk-toggle summary:hover{background:var(--nk-bg-hover)}.nk-toggle summary:before{content:\"\\25b8\";color:var(--nk-text-tertiary);font-size:11px;transition:transform .15s;display:inline-block}.nk-toggle[open] summary:before{transform:rotate(90deg)}.nk-toggle .toggle-body,.nk-toggle ::slotted(.toggle-body){padding:4px 0 8px 26px;color:var(--nk-text-secondary);line-height:1.55}.nk-divider{border:none;border-top:1px solid var(--nk-border);margin:24px 0}.nk-quote{border-left:3px solid var(--nk-text);padding:2px 0 2px 14px;margin:16px 0;color:var(--nk-text-secondary);line-height:1.5}.nk-quote .q-cite{display:block;margin-top:6px;font-size:12.5px;color:var(--nk-text-tertiary)}.nk-mention{display:inline-flex;align-items:center;gap:4px;padding:0 4px;border-radius:4px;font-weight:500;cursor:pointer;white-space:nowrap}.nk-mention:hover{background:var(--nk-bg-hover)}.nk-mention.person{color:var(--nk-text)}.nk-mention.person .mini-avatar,.nk-mention.person .nk-avatar,.nk-mention.person ::slotted(.mini-avatar),.nk-mention.person ::slotted([slot=\"avatar\"]){width:16px;height:16px;border-radius:50%;color:var(--nk-on-accent);font-size:8.5px;font-weight:600;display:inline-flex;align-items:center;justify-content:center}.nk-mention.page{color:var(--nk-text-secondary);text-decoration:underline;text-decoration-color:var(--nk-border-strong);text-underline-offset:2px}.nk-mention.date{color:var(--nk-color-orange)}.nk-inline-code{font-family:var(--nk-font-mono);font-size:85%;color:var(--nk-danger);background:color-mix(in srgb,var(--nk-danger) 8%,transparent);border-radius:4px;padding:1px 5px}.nk-code{background:var(--nk-bg-code);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:20px 24px;font-family:var(--nk-font-mono);font-size:13px;line-height:1.6;margin:14px 0;overflow-x:auto;color:var(--nk-text-secondary);white-space:pre;position:relative}.nk-code .lang{position:absolute;top:6px;right:10px;font-size:11px;color:var(--nk-text-tertiary);font-family:var(--nk-font)}.nk-code .tag,.nk-code ::slotted(.tag){color:var(--nk-accent)}.nk-code .attr,.nk-code ::slotted(.attr){color:var(--nk-color-orange)}.nk-database{margin:12px 0 8px}.nk-db-tabs{display:flex;gap:2px;align-items:center;padding:0 0 6px;margin-bottom:0;font-size:14px}.nk-db-tab{padding:4px 8px;cursor:pointer;color:var(--nk-text-secondary);border-radius:var(--nk-radius);user-select:none;line-height:20px;display:flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap}.nk-db-tab:hover{color:var(--nk-text);background:var(--nk-bg-hover)}.nk-db-tab.active{color:var(--nk-text);background:var(--nk-bg-active);font-weight:500}.nk-db-tab.add{color:var(--nk-text-tertiary)}.nk-db-tab .badge,.nk-db-tab ::slotted(.badge){background:var(--nk-bg-callout);border-radius:8px;font-size:11px;padding:0 6px;color:var(--nk-text-tertiary)}.nk-db-toolbar{display:flex;align-items:center;gap:8px;min-width:0;padding-bottom:6px}.nk-db-toolbar>.nk-db-tabs{flex:1 1 auto;min-width:0;padding-bottom:0;overflow-x:auto;scrollbar-width:none}.nk-db-toolbar>.nk-db-tabs::-webkit-scrollbar{display:none}.nk-db-toolbar .tools{flex:none;display:flex;align-items:center;gap:4px;margin-left:auto}.nk-db-tool{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 8px;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:14px;color:var(--nk-text-secondary);white-space:nowrap;cursor:pointer;user-select:none}.nk-db-tool:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-db-tool.active{color:var(--nk-accent)}.nk-filter-row{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:2px 0 8px}.nk-filter-pill{display:inline-flex;align-items:center;gap:4px;height:24px;padding:0 8px;border:1px solid var(--nk-border-strong);border-radius:12px;background:transparent;font-family:inherit;font-size:13px;line-height:1;color:var(--nk-text-secondary);white-space:nowrap;cursor:pointer;user-select:none}.nk-filter-pill:hover{background:var(--nk-bg-hover)}.nk-filter-pill.active{color:var(--nk-accent);border-color:color-mix(in srgb,var(--nk-accent) 35%,transparent);background:color-mix(in srgb,var(--nk-accent) 6%,transparent)}.nk-filter-pill.add{border-color:transparent;color:var(--nk-text-tertiary)}.nk-filter-pill.add:hover{color:var(--nk-text-secondary)}.nk-filter-pill button{padding:0;border:none;background:none;font:inherit;color:inherit;cursor:pointer}.nk-filter-pill .fp-remove{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:-4px;border-radius:50%;font-size:13px}.nk-filter-pill .fp-remove:hover{background:color-mix(in srgb,currentColor 15%,transparent)}.nk-table-wrap{overflow-x:auto}.nk-table{width:100%;border-collapse:collapse;font-size:14px}.nk-table th{text-align:left;font-weight:400;color:var(--nk-text-secondary);height:36px;padding:0 8px;border-bottom:1px solid var(--nk-border);border-right:1px solid var(--nk-border);font-size:14px;white-space:nowrap;user-select:none;cursor:pointer}.nk-table th:hover{background:var(--nk-bg-hover)}.nk-table th .th-icon,.nk-table th ::slotted(.th-icon){margin-right:6px;font-size:13px;color:var(--nk-text-tertiary)}.nk-table td{height:36px;padding:6px 8px;line-height:1.5;border-bottom:1px solid var(--nk-border);border-right:1px solid var(--nk-border);white-space:nowrap;vertical-align:middle}.nk-table th:last-child,.nk-table td:last-child{border-right:none}.nk-table.wrap td,.nk-table td.wrap{white-space:normal;vertical-align:top}.nk-table tbody tr:hover{background:var(--nk-bg-hover)}.nk-table .row-title{display:flex;align-items:center;gap:7px;font-weight:500;cursor:pointer}.nk-table .row-title:hover{text-decoration:underline;text-decoration-color:var(--nk-text-tertiary)}.nk-table .date-cell{color:var(--nk-text-secondary)}.nk-table .num{text-align:right;font-variant-numeric:tabular-nums}.nk-table .person-cell{display:flex;align-items:center;gap:6px;color:var(--nk-text-secondary)}.nk-table .person-cell .mini-avatar,.nk-table .person-cell ::slotted(.mini-avatar){width:20px;height:20px;border-radius:50%;font-size:10px;color:var(--nk-on-accent);display:inline-flex;align-items:center;justify-content:center;font-weight:600}.nk-new-row,.nk-table .new-row{color:var(--nk-text-tertiary);cursor:pointer;padding:8px;display:flex;align-items:center;gap:7px;font-size:14px}.nk-new-row:hover,.nk-table .new-row:hover{background:var(--nk-bg-hover)}.nk-tag{display:inline-flex;align-items:center;max-width:100%;height:20px;padding:0 6px;border-radius:3px;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;background:var(--nk-tag-gray-bg);color:var(--nk-tag-gray-text)}.nk-tag.gray{background:var(--nk-tag-gray-bg);color:var(--nk-tag-gray-text)}.nk-tag.brown{background:var(--nk-tag-brown-bg);color:var(--nk-tag-brown-text)}.nk-tag.orange{background:var(--nk-tag-orange-bg);color:var(--nk-tag-orange-text)}.nk-tag.yellow{background:var(--nk-tag-yellow-bg);color:var(--nk-tag-yellow-text)}.nk-tag.green{background:var(--nk-tag-green-bg);color:var(--nk-tag-green-text)}.nk-tag.blue{background:var(--nk-tag-blue-bg);color:var(--nk-tag-blue-text)}.nk-tag.purple{background:var(--nk-tag-purple-bg);color:var(--nk-tag-purple-text)}.nk-tag.pink{background:var(--nk-tag-pink-bg);color:var(--nk-tag-pink-text)}.nk-tag.red{background:var(--nk-tag-red-bg);color:var(--nk-tag-red-text)}.nk-progress{width:110px;height:6px;border-radius:3px;background:var(--nk-tint-blue);overflow:hidden;display:inline-block}.nk-progress>i{display:block;height:100%;background:var(--nk-color-blue);border-radius:3px}.nk-progress.wide{width:100%;flex:1 1 60px}.nk-progress-label{font-size:12px;color:var(--nk-text-tertiary);margin-left:7px;white-space:nowrap}.nk-list{display:flex;flex-direction:column;font-size:14px}.nk-list-item{display:flex;align-items:center;gap:8px;min-width:0;overflow:hidden;min-height:36px;padding:4px 6px;border-bottom:1px solid var(--nk-border);color:inherit;text-decoration:none;cursor:pointer}.nk-list-item:hover{background:var(--nk-bg-hover)}.nk-list>.nk-list-item:last-child,.nk-list ::slotted(.nk-list-item:last-child),.nk-list-item.last{border-bottom:none}.nk-list-item .l-icon,.nk-list-item ::slotted([slot=\"icon\"]){width:20px;flex-shrink:0;text-align:center;font-size:15px}.nk-list-item .l-title,.nk-list-item ::slotted(.l-title){flex:1 1 auto;min-width:0;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-list-item .l-meta,.nk-list-item ::slotted(.l-meta){flex:none;display:flex;align-items:center;gap:8px;margin-left:auto;font-size:12px;color:var(--nk-text-secondary);white-space:nowrap}.nk-calendar-view{font-size:14px}.nk-calendar-view .cv-head{display:flex;align-items:center;gap:4px;padding:2px 0 8px}.nk-calendar-view .cv-title{flex:1;font-weight:600;white-space:nowrap}.nk-calendar-view .cv-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));border-top:1px solid var(--nk-border);border-left:1px solid var(--nk-border)}.nk-calendar-view.weeks .cv-grid{grid-template-columns:32px repeat(7,minmax(0,1fr))}.nk-calendar-view :is(.cv-wd,.cv-week,.cv-day){min-width:0;border-right:1px solid var(--nk-border);border-bottom:1px solid var(--nk-border)}.nk-calendar-view .cv-wd{padding:4px 8px;font-size:12px;color:var(--nk-text-secondary);text-align:center}.nk-calendar-view .cv-week{padding:6px 0;font-size:11px;color:var(--nk-text-tertiary);text-align:center;font-variant-numeric:tabular-nums}.nk-calendar-view .cv-day{display:flex;flex-direction:column;gap:3px;min-height:112px;padding:4px 4px 6px}.nk-calendar-view .cv-day:is(.out,.off){background:var(--nk-bg-sidebar)}.nk-calendar-view .cv-num{align-self:flex-end;min-width:22px;height:22px;padding:0 6px;border-radius:11px;font-size:13px;line-height:22px;text-align:center;color:var(--nk-text-secondary);font-variant-numeric:tabular-nums}.nk-calendar-view .cv-day.out .cv-num{color:var(--nk-text-tertiary)}.nk-calendar-view .cv-day.today .cv-num{background:var(--nk-danger);color:var(--nk-on-accent)}.nk-calendar-view .cv-item{display:block;min-width:0;padding:3px 6px;border-radius:4px;background:var(--nk-bg-card);border:1px solid var(--nk-border);box-shadow:var(--nk-shadow-card);font-size:12.5px;line-height:18px;color:var(--nk-text);text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}.nk-calendar-view .cv-item:hover{background:var(--nk-bg-hover)}.nk-board{display:none;gap:12px;padding:14px 2px;overflow-x:auto}.nk-board.active{display:flex}.nk-board-col{min-width:220px;width:220px;flex-shrink:0}.nk-board-col-header{display:flex;align-items:center;gap:7px;margin-bottom:8px;font-size:13.5px;font-weight:500}.nk-board-col-header .count{color:var(--nk-text-tertiary);font-weight:400}.nk-card{background:var(--nk-bg-card);border:1px solid var(--nk-border);border-radius:8px;padding:10px 12px;margin-bottom:8px;cursor:grab;box-shadow:var(--nk-shadow-card);transition:border-color .15s}.nk-card:hover{border-color:var(--nk-border-strong)}.nk-card .card-title,.nk-card ::slotted(.card-title){font-weight:500;margin-bottom:7px;display:flex;gap:6px;align-items:center}.nk-card .card-meta,.nk-card ::slotted(.card-meta){display:flex;gap:6px;flex-wrap:wrap;align-items:center;font-size:12px;color:var(--nk-text-secondary)}.nk-field{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:9px 0}.nk-field .f-label,.nk-field ::slotted(.f-label),.nk-field ::slotted([slot=\"label\"]){font-size:14px}.nk-field .f-desc,.nk-field ::slotted(.f-desc),.nk-field ::slotted([slot=\"desc\"]){font-size:12px;color:var(--nk-text-secondary);margin-top:2px;line-height:1.45}.nk-field .f-control,.nk-field ::slotted(.f-control){flex-shrink:0}.nk-field.stacked,.nk-fields>.nk-field{flex-direction:column;align-items:stretch;gap:6px;min-width:0}.nk-field.stacked .f-control,.nk-fields>.nk-field .f-control{width:100%;min-width:0}.nk-field.stacked .nk-input,.nk-field.stacked .nk-textarea,.nk-field.stacked .nk-select,.nk-fields>.nk-field .nk-input,.nk-fields>.nk-field .nk-textarea,.nk-fields>.nk-field .nk-select{width:100%;min-width:0}.nk-field.compact,.nk-fields>.nk-field{padding:0;gap:4px;min-width:0}.nk-field.compact .f-label,.nk-field.compact ::slotted([slot=\"label\"]),.nk-fields>.nk-field .f-label,.nk-fields>.nk-field ::slotted([slot=\"label\"]){font-size:12px;color:var(--nk-text-tertiary)}.nk-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px 12px;padding:9px 0}.nk-fields>.nk-field{min-width:0}.nk-input,.nk-select,.nk-textarea{font-family:inherit;font-size:14px;line-height:20px;color:var(--nk-text);background:var(--nk-bg-input);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:5px 10px;outline:none;transition:border-color .15s,box-shadow .15s;min-width:210px}.nk-input:hover,.nk-select:hover,.nk-textarea:hover{border-color:var(--nk-border-strong)}.nk-input:focus,.nk-select:focus,.nk-textarea:focus{border-color:color-mix(in srgb,var(--nk-accent) 60%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 30%,transparent)}.nk-input::placeholder,.nk-textarea::placeholder{color:var(--nk-text-tertiary)}.nk-input.wide,.nk-textarea.wide,.nk-select.wide{width:100%;min-width:0}.nk-input[type=date],.nk-input[type=time],.nk-input[type=datetime-local],.nk-input[type=month]{appearance:none}.nk-input::-webkit-date-and-time-value{text-align:start;min-height:1lh}.nk-select.compact{min-width:120px}.nk-textarea{resize:vertical;min-height:70px;line-height:1.5}.nk-select{appearance:none;cursor:pointer;padding-right:26px;background-image:linear-gradient(45deg,transparent 50%,var(--nk-text-tertiary) 50%),linear-gradient(135deg,var(--nk-text-tertiary) 50%,transparent 50%);background-position:calc(100% - 14px) 55%,calc(100% - 10px) 55%;background-size:4px 4px;background-repeat:no-repeat}.nk-copy-field{display:flex;align-items:center;gap:2px;min-width:210px;max-width:100%;padding:0 3px 0 10px;font-size:14px;line-height:20px;color:var(--nk-text);background:var(--nk-bg-input);border:1px solid var(--nk-border);border-radius:var(--nk-radius)}.nk-copy-field.wide{width:100%;min-width:0}.nk-copy-field.wrap{align-items:flex-start}.nk-copy-field .cf-value{flex:1 1 auto;min-width:0;padding:5px 6px 5px 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;user-select:all}.nk-copy-field.mono .cf-value{font-family:var(--nk-font-mono);font-size:13px}.nk-copy-field.wrap .cf-value{white-space:pre-wrap;overflow-wrap:anywhere}.nk-copy-field .cf-btn{flex:none;height:24px;margin:3px 0;padding:0 8px;border:none;border-radius:4px;background:transparent;font-family:inherit;font-size:13px;color:var(--nk-text-secondary);white-space:nowrap;cursor:pointer}.nk-copy-field .cf-btn:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-copy-field .cf-btn.copied{color:var(--nk-color-green)}.nk-calendar{display:block;width:max-content;max-width:100%;margin-inline:auto;font-size:14px;user-select:none;-webkit-user-select:none}.nk-calendar .cal-head{display:flex;align-items:center;gap:2px;padding:0 0 6px 6px}.nk-calendar .cal-title{flex:1;font-weight:600;white-space:nowrap}.nk-calendar .cal-nav,.nk-calendar-view .cal-nav{display:inline-flex;align-items:center;justify-content:center;height:28px;min-width:28px;padding:0 6px;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:13px;color:var(--nk-text-secondary);cursor:pointer}.nk-calendar .cal-nav:hover,.nk-calendar-view .cal-nav:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-calendar .cal-nav svg,.nk-calendar-view .cal-nav svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.nk-calendar .cal-grid{display:grid;grid-template-columns:repeat(7,var(--_nk-cell, 36px));row-gap:2px}.nk-calendar.weeks .cal-grid{grid-template-columns:24px repeat(7,var(--_nk-cell, 36px))}.nk-calendar .cal-wd,.nk-calendar .cal-week{display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--nk-text-tertiary);font-variant-numeric:tabular-nums}.nk-calendar .cal-wd{height:24px}.nk-calendar .cal-week{font-size:11px}.nk-calendar .cal-day{position:relative;display:inline-flex;align-items:center;justify-content:center;width:var(--_nk-cell, 36px);height:var(--_nk-cell, 36px);padding:0;border:none;border-radius:var(--nk-radius);background:transparent;font-family:inherit;font-size:14px;color:var(--nk-text);font-variant-numeric:tabular-nums;cursor:pointer}.nk-calendar .cal-day:hover{background:var(--nk-bg-hover)}.nk-calendar .cal-day:focus-visible{outline:2px solid color-mix(in srgb,var(--nk-accent) 60%,transparent);outline-offset:-2px}.nk-calendar .cal-day.out,.nk-calendar .cal-day.off{color:var(--nk-text-tertiary)}.nk-calendar .cal-day.today{color:var(--nk-danger);font-weight:600}.nk-calendar .cal-day.in-range{border-radius:0;background:color-mix(in srgb,var(--nk-accent) 12%,transparent)}.nk-calendar .cal-day:is(.selected,.start,.end){background:var(--nk-accent);color:var(--nk-on-accent);font-weight:500}.nk-calendar .cal-day.start:not(.end){border-radius:var(--nk-radius) 0 0 var(--nk-radius)}.nk-calendar .cal-day.end:not(.start){border-radius:0 var(--nk-radius) var(--nk-radius) 0}.nk-calendar .cal-day[aria-disabled=true]{color:var(--nk-text-tertiary);background:none;opacity:.5;cursor:default}.nk-calendar .cal-marks{position:absolute;left:0;right:0;bottom:3px;display:flex;justify-content:center;gap:2px;pointer-events:none}.nk-calendar .cal-marks i{width:4px;height:4px;border-radius:50%;background:var(--nk-color-gray)}.nk-calendar .cal-day:is(.selected,.start,.end) .cal-marks i{background:var(--nk-on-accent)}.nk-calendar .cal-foot{display:flex;align-items:center;gap:8px;margin-top:8px;padding:8px 2px 0;border-top:1px solid var(--nk-border)}.nk-calendar .cal-foot .nk-input{min-width:0;flex:1 1 auto}.nk-btn{font-family:inherit;font-size:14px;line-height:20px;font-weight:500;border-radius:var(--nk-radius);cursor:pointer;padding:3px 12px;border:1px solid transparent;transition:background .15s,border-color .15s,box-shadow .15s,opacity .15s;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}.nk-btn svg,.nk-btn ::slotted(svg){width:15px;height:15px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.nk-btn.primary{background:var(--nk-accent);color:var(--nk-on-accent)}.nk-btn.primary:hover{opacity:.88}.nk-btn.secondary{background:var(--nk-bg-card);color:var(--nk-text);box-shadow:var(--nk-shadow-btn)}.nk-btn.secondary:hover{background:color-mix(in srgb,var(--nk-bg-card),var(--nk-text) 6%)}.nk-btn.danger{background:var(--nk-bg-card);color:var(--nk-danger);box-shadow:var(--nk-shadow-btn)}.nk-btn.danger:hover{background:color-mix(in srgb,var(--nk-danger) 8%,var(--nk-bg-card))}.nk-btn.danger-solid{background:var(--nk-danger);color:var(--nk-on-accent)}.nk-btn.danger-solid:hover{opacity:.88}.nk-btn.small{padding:1px 8px;font-size:13px;line-height:20px}a.nk-btn{text-decoration:none}.nk-btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.nk-switch{position:relative;width:34px;height:20px;flex-shrink:0;appearance:none;border:none;cursor:pointer;border-radius:20px;background:var(--nk-border-strong);transition:background .2s}.nk-switch:after{content:\"\";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--nk-on-accent);transition:transform .2s;box-shadow:var(--nk-shadow-knob)}.nk-switch:checked,.nk-switch[aria-checked=true]{background:var(--nk-accent)}.nk-switch:checked:after,.nk-switch[aria-checked=true]:after{transform:translate(14px)}.nk-switch:disabled{opacity:.5;cursor:not-allowed}.nk-switch-label{display:inline-flex;align-items:flex-start;gap:8px;font-size:14px;cursor:pointer}.nk-switch-label>.nk-switch{font-size:inherit;line-height:inherit;margin-top:max(0px,calc((1lh - 20px)/2))}.nk-switch-label>span{padding-top:max(0px,calc((20px - 1lh)/2))}.nk-switch-label:has(.nk-switch:disabled){cursor:not-allowed;color:var(--nk-text-tertiary)}.nk-check{display:flex;align-items:flex-start;gap:8px;padding:4px 0;font-size:14px;cursor:pointer}.nk-check input{appearance:none;width:16px;height:16px;flex-shrink:0;border:1.4px solid var(--nk-border-strong);border-radius:3px;cursor:pointer;position:relative;background:var(--nk-bg);font-size:inherit;line-height:inherit;margin-top:max(0px,calc((1lh - 16px)/2))}.nk-check input[type=radio]{border-radius:50%}.nk-check input:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-check input:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:10.5px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-check input[type=radio]:checked:after{content:\"\\25cf\";font-size:7px}.nk-check input:disabled{opacity:.5;cursor:not-allowed}.nk-check input:disabled+*{opacity:.6}.nk-slider{width:210px;accent-color:var(--nk-accent);cursor:pointer}.nk-slider-value{font-size:12.5px;color:var(--nk-text-tertiary);margin-top:3px}.nk-profile-row{display:flex;align-items:center;gap:14px;padding:8px 0}.nk-profile-row .big-avatar,.nk-profile-row ::slotted(.big-avatar),.nk-profile-row ::slotted([slot=\"avatar\"]){width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:20px;font-weight:600;display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.nk-profile-row .big-avatar>img{display:block;width:100%;height:100%;object-fit:cover}.nk-profile-row .big-avatar.square,.nk-profile-row ::slotted(.big-avatar.square){border-radius:8px}.nk-profile-row .pr-actions{display:flex;flex-direction:column;gap:6px}.nk-profile-row .pr-remove{color:var(--nk-text-tertiary)}.nk-model-card{border:1px solid var(--nk-border-strong);border-radius:8px;padding:12px 14px;margin-bottom:10px;cursor:pointer;display:flex;align-items:flex-start;gap:11px;transition:border-color .15s,background .15s}.nk-model-card:hover{background:var(--nk-bg-hover)}.nk-model-card.selected{border-color:var(--nk-accent);background:color-mix(in srgb,var(--nk-accent) 6%,transparent)}.nk-model-card .m-radio{width:15px;height:15px;border-radius:50%;flex-shrink:0;margin-top:2px;border:1.4px solid var(--nk-border-strong);position:relative}.nk-model-card.selected .m-radio{border-color:var(--nk-accent)}.nk-model-card.selected .m-radio:after{content:\"\";position:absolute;inset:3px;border-radius:50%;background:var(--nk-accent)}.nk-model-card .m-name,.nk-model-card ::slotted(.m-name),.nk-model-card ::slotted([slot=\"title\"]){font-weight:500;font-size:14px;display:flex;align-items:center;gap:7px}.nk-model-card .m-desc,.nk-model-card ::slotted(.m-desc),.nk-model-card ::slotted([slot=\"desc\"]){font-size:12px;color:var(--nk-text-secondary);margin-top:2px;line-height:1.45}.nk-danger-zone{border:1px solid color-mix(in srgb,var(--nk-danger) 40%,transparent);border-radius:8px;padding:14px 16px;margin-top:26px}.nk-danger-zone .dz-title{color:var(--nk-danger);font-weight:600;font-size:13px;margin-bottom:8px}.nk-member-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--nk-border)}.nk-member-list>.nk-member-row:last-child,.nk-member-list ::slotted(.nk-member-row:last-child),.nk-member-row.last{border-bottom:none}.nk-member-row .mini-avatar,.nk-member-row .nk-avatar,.nk-member-row ::slotted(.mini-avatar),.nk-member-row ::slotted([slot=\"avatar\"]){width:28px;height:28px;border-radius:50%;color:var(--nk-on-accent);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;flex-shrink:0}.nk-member-row>:has(>.m-mail){min-width:0}.nk-member-row .m-mail{font-size:12px;color:var(--nk-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nk-member-row .nk-select{min-width:120px;margin-left:auto}.nk-member-row ::slotted([slot=\"role\"]){margin-left:auto}.nk-modal-backdrop{position:fixed;inset:0;background:var(--nk-scrim);padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);display:flex;align-items:center;justify-content:center;z-index:100;opacity:0;pointer-events:none;transition:opacity .2s ease}.nk-modal-backdrop.open{opacity:1;pointer-events:auto}.nk-modal{width:min(1150px,92vw);height:min(715px,86vh);max-width:100%;max-height:100%;background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);display:flex;overflow:hidden;transform:scale(.98) translateY(6px);transition:transform .2s ease}.nk-modal-backdrop.open .nk-modal{transform:scale(1) translateY(0)}.nk-settings-nav{width:240px;min-width:240px;background:var(--nk-bg-sidebar);border-right:1px solid var(--nk-border);padding:10px 8px;overflow-y:auto;flex-shrink:0}.nk-settings-user{display:flex;align-items:center;gap:9px;padding:6px 10px 12px;margin-bottom:4px}.nk-settings-user .avatar,.nk-settings-user ::slotted(.avatar),.nk-settings-user ::slotted([slot=\"avatar\"]){width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-weight:600;font-size:13px;display:flex;align-items:center;justify-content:center}.nk-settings-user .name{font-weight:500;font-size:14px}.nk-settings-user .mail{font-size:12px;color:var(--nk-text-secondary)}.nk-settings-nav .nk-tree-item{min-height:28px}.nk-settings-nav .nk-tree-item.active{background:var(--nk-bg-active);color:var(--nk-text);font-weight:500}.nk-settings-content{flex:1;overflow-y:auto;padding:36px 60px 80px;min-width:0}.nk-settings-content::-webkit-scrollbar{width:10px}.nk-settings-content::-webkit-scrollbar-thumb{background:var(--nk-border-strong);border-radius:5px;border:2px solid var(--nk-bg)}.nk-settings-pane{display:none;max-width:800px}.nk-settings-pane.active{display:block}.nk-settings-pane>h2{font-size:22px;font-weight:600;line-height:1.3;margin-bottom:20px}.nk-settings-pane>h3{font-size:16px;font-weight:500;padding-bottom:8px;border-bottom:1px solid var(--nk-border);margin:30px 0 12px}.nk-settings-pane ::slotted(h2){font-size:22px;font-weight:600;line-height:1.3;padding:0!important;margin:0 0 20px!important}.nk-settings-pane ::slotted(h3){font-size:16px;font-weight:500;border:0;border-bottom:1px solid var(--nk-border);padding:0 0 8px!important;margin:30px 0 12px!important}.nk-pop{background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);padding:10px;width:296px}.nk-emoji-search{width:100%;font-family:inherit;font-size:14px;color:var(--nk-text);background:var(--nk-bg-input);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:6px 10px;outline:none;margin-bottom:8px}.nk-emoji-grid{display:grid;grid-template-columns:repeat(8,1fr);gap:2px}.nk-emoji-grid span,.nk-emoji-grid ::slotted(span){font-size:18px;text-align:center;padding:4px 0;border-radius:5px;cursor:pointer;user-select:none}.nk-emoji-grid span:hover{background:var(--nk-bg-hover)}.nk-emoji-cats{display:flex;gap:2px;margin-top:8px;padding-top:8px;border-top:1px solid var(--nk-border)}.nk-emoji-cats span{font-size:14px;padding:3px 7px;border-radius:5px;cursor:pointer;color:var(--nk-text-tertiary);filter:grayscale(1);opacity:.6}.nk-emoji-cats span.active,.nk-emoji-cats span:hover{filter:none;opacity:1;background:var(--nk-bg-hover)}.nk-menu{padding:5px;width:230px}.nk-menu-item{display:flex;align-items:center;gap:9px;padding:4px 8px;min-height:var(--_nk-row, 28px);border-radius:5px;cursor:pointer;font-size:14px;user-select:none}.nk-menu-item:hover{background:var(--nk-bg-hover)}.nk-menu-item .m-icon,.nk-menu-item ::slotted(.m-icon),.nk-menu-item ::slotted([slot=\"icon\"]){width:17px;text-align:center;font-size:14px}.nk-menu-item .m-shortcut,.nk-menu-item ::slotted(.m-shortcut){margin-left:auto;font-size:12px;color:var(--nk-text-tertiary)}.nk-menu-item.danger{color:var(--nk-danger)}.nk-menu-item>.nk-switch{margin-left:auto}.nk-menu-sep{border-top:1px solid var(--nk-border);margin:5px 4px}.nk-menu-label{font-size:12px;color:var(--nk-text-tertiary);padding:5px 8px 2px}.nk-pop.floating{z-index:60;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-4px) scale(.98);transform-origin:top;transition:opacity .15s ease,transform .15s ease,visibility 0s linear .15s}.nk-pop.floating.open{opacity:1;visibility:visible;pointer-events:auto;transform:none;transition:opacity .15s ease,transform .15s ease,visibility 0s}.nk-cmdk-backdrop{position:fixed;inset:0;background:var(--nk-scrim-soft);display:flex;justify-content:center;align-items:flex-start;padding:max(14vh,env(safe-area-inset-top,0px)) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);z-index:110;opacity:0;pointer-events:none;transition:opacity .18s ease}.nk-cmdk-backdrop.open{opacity:1;pointer-events:auto}.nk-cmdk{max-width:100%;width:min(560px,92vw);background:var(--nk-bg);border-radius:12px;box-shadow:var(--nk-shadow-menu);overflow:hidden;transform:scale(.98);transition:transform .18s ease}.nk-cmdk-backdrop.open .nk-cmdk{transform:scale(1)}.nk-cmdk-input-row{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--nk-border)}.nk-cmdk-input-row input{flex:1;border:none;outline:none;background:transparent;font-family:inherit;font-size:16px;color:var(--nk-text)}.nk-cmdk-input-row input::placeholder{color:var(--nk-text-tertiary)}.nk-cmdk-list{max-height:320px;overflow-y:auto;padding:6px}.nk-cmdk-group{font-size:12px;color:var(--nk-text-tertiary);padding:8px 10px 3px}.nk-cmdk-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:14px;user-select:none}.nk-cmdk-item.selected{background:var(--nk-bg-active)}.nk-cmdk-item .m-icon,.nk-cmdk-item ::slotted(.m-icon),.nk-cmdk-item ::slotted([slot=\"icon\"]){width:17px;text-align:center;font-size:14px}.nk-cmdk-item .m-shortcut,.nk-cmdk-item ::slotted(.m-shortcut){margin-left:auto;font-size:12px;color:var(--nk-text-tertiary)}.nk-cmdk-empty{padding:30px;text-align:center;color:var(--nk-text-tertiary);font-size:13.5px}.nk-cmdk-footer{display:flex;gap:14px;padding:8px 16px;border-top:1px solid var(--nk-border);font-size:11.5px;color:var(--nk-text-tertiary)}.nk-sheet-backdrop{position:fixed;inset:0;z-index:100;display:none;flex-direction:column;align-items:center;justify-content:flex-end;padding-top:max(24px,env(safe-area-inset-top,0px));background:var(--nk-scrim-soft);opacity:0;transition:opacity .2s ease,display .25s allow-discrete}.nk-sheet-backdrop.open{display:flex;opacity:1}@starting-style{.nk-sheet-backdrop.open{opacity:0}}.nk-sheet{--_nk-row: 40px;width:100%;max-width:640px;max-height:100%;overflow-y:auto;overscroll-behavior:contain;padding:6px max(10px,env(safe-area-inset-right,0px)) max(16px,env(safe-area-inset-bottom,0px)) max(10px,env(safe-area-inset-left,0px));background:var(--nk-bg);color:var(--nk-text);border-radius:14px 14px 0 0;box-shadow:var(--nk-shadow-menu);translate:0 100%;transition:translate .25s cubic-bezier(.2,.8,.2,1)}.nk-sheet-backdrop.open .nk-sheet{translate:0 0}@starting-style{.nk-sheet-backdrop.open .nk-sheet{translate:0 100%}}.nk-sheet .sh-grabber,.nk-sheet ::slotted(.sh-grabber){width:36px;height:4px;margin:4px auto 10px;border-radius:2px;background:var(--nk-border-strong)}.nk-sheet .sh-title,.nk-sheet ::slotted(.sh-title){font-size:14px;font-weight:600;text-align:center;padding:0 8px 10px}.nk-peek-backdrop{position:fixed;inset:0;z-index:50;display:none;pointer-events:none;transition:background-color .2s ease,display .25s allow-discrete}.nk-peek-backdrop.open{display:block}.nk-peek{--_nk-title: 32px;position:absolute;top:0;right:0;bottom:0;width:min(560px,100%);display:flex;flex-direction:column;pointer-events:auto;outline:none;background:var(--nk-bg);color:var(--nk-text);box-shadow:var(--nk-shadow-menu);translate:100% 0;transition:translate .25s cubic-bezier(.2,.8,.2,1)}.nk-peek-backdrop.open .nk-peek{translate:0 0}@starting-style{.nk-peek-backdrop.open .nk-peek{translate:100% 0}}.nk-peek .pk-bar{flex:none;display:flex;align-items:center;gap:2px;height:44px;padding:0 12px}.nk-peek .pk-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:4px 48px 64px;font-size:16px;line-height:1.5}.nk-toast{position:fixed;bottom:max(20px,calc(env(safe-area-inset-bottom,0px) + 12px));left:50%;transform:translate(-50%) translateY(80px);z-index:120;width:max-content;max-width:calc(100% - 32px);background:var(--nk-text);color:var(--nk-bg);padding:8px 16px;border-radius:8px;font-size:14px;opacity:0;transition:all .3s ease;pointer-events:none;box-shadow:var(--nk-shadow-menu);display:flex;gap:8px;align-items:center}.nk-toast.show{opacity:1;transform:translate(-50%) translateY(0)}.nk-gallery-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));gap:20px 32px;margin:12px 0}.nk-g-item>h4{font-size:12px;font-weight:500;color:var(--nk-text-tertiary);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}.nk-g-item ::slotted(h4){font-size:12px;font-weight:500;color:var(--nk-text-tertiary);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px!important}.nk-tabs{display:flex;gap:2px;border-bottom:1px solid var(--nk-border);font-size:14px}.nk-tab{padding:7px 11px;cursor:pointer;color:var(--nk-text-secondary);border-bottom:2px solid transparent;margin-bottom:-1px;user-select:none}.nk-tab:hover{color:var(--nk-text)}.nk-tab.active{color:var(--nk-text);border-bottom-color:var(--nk-text);font-weight:500}.nk-tab-panel{padding:12px 2px;color:var(--nk-text-secondary);line-height:1.55;font-size:14px}.nk-template-btn{display:flex;align-items:center;gap:8px;width:100%;font-family:inherit;font-size:14px;color:var(--nk-text-secondary);background:var(--nk-bg-callout);border:none;border-radius:var(--nk-radius);padding:8px 12px;cursor:pointer;margin-bottom:6px;text-align:left}.nk-template-btn:hover{background:var(--nk-bg-hover)}.nk-stats{display:flex;gap:10px}.nk-stat{flex:1;border:1px solid var(--nk-border);border-radius:8px;padding:12px 14px}.nk-stat .s-label,.nk-stat ::slotted(.s-label),.nk-stat ::slotted([slot=\"label\"]){font-size:12px;color:var(--nk-text-secondary);margin-bottom:4px}.nk-stat .s-value,.nk-stat ::slotted(.s-value),.nk-stat ::slotted([slot=\"value\"]){font-size:22px;font-weight:600;letter-spacing:-.01em}.nk-stat .s-delta,.nk-stat ::slotted(.s-delta),.nk-stat ::slotted([slot=\"delta\"]){font-size:12px;margin-top:3px}.nk-stat .s-delta.up,.nk-stat ::slotted(.s-delta.up),.nk-stat ::slotted([slot=\"delta\"].up){color:var(--nk-color-green)}.nk-stat .s-delta.down,.nk-stat ::slotted(.s-delta.down),.nk-stat ::slotted([slot=\"delta\"].down){color:var(--nk-danger)}.nk-synced{border:1.5px solid color-mix(in srgb,var(--nk-danger) 55%,transparent);border-radius:8px;padding:12px 14px;position:relative;margin:8px 0}.nk-synced .synced-badge{position:absolute;top:-9px;right:10px;font-size:11px;background:var(--nk-danger);color:var(--nk-on-accent);border-radius:8px;padding:1px 8px}.nk-segmented{display:inline-flex;background:var(--nk-bg-callout);border-radius:7px;padding:2px}.nk-segmented button{font-family:inherit;font-size:14px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 12px;border-radius:5px;cursor:pointer}.nk-segmented ::slotted(button){font-family:inherit;font-size:14px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 12px!important;border-radius:5px;cursor:pointer}.nk-segmented button.active,.nk-segmented ::slotted(button.active){background:var(--nk-bg);color:var(--nk-text);font-weight:500;box-shadow:var(--nk-shadow-segment)}.nk-segmented.wrap{flex-wrap:wrap}.nk-segmented.scroll{max-width:100%;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}.nk-segmented.scroll::-webkit-scrollbar{display:none}.nk-segmented.scroll button,.nk-segmented.scroll ::slotted(button){flex-shrink:0;white-space:nowrap}.nk-banner{display:flex;align-items:center;gap:10px;font-size:14px;border-radius:8px;padding:10px 14px;margin-bottom:8px;color:var(--nk-text)}.nk-banner.info{background:var(--nk-tint-blue)}.nk-banner.success{background:var(--nk-tint-green)}.nk-banner.warning{background:var(--nk-tint-yellow)}.nk-banner.danger{background:var(--nk-tint-red)}.nk-banner .b-action,.nk-banner ::slotted(.b-action),.nk-banner ::slotted([slot=\"action\"]){margin-left:auto;font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px}.nk-avatar-group{display:flex}.nk-avatar-group .mini-avatar,.nk-avatar-group .nk-avatar,.nk-avatar-group ::slotted(.mini-avatar),.nk-avatar-group ::slotted(.nk-avatar){width:26px;height:26px;border-radius:50%;color:var(--nk-on-accent);font-size:10.5px;font-weight:600;border:2px solid var(--nk-bg);display:flex;align-items:center;justify-content:center;margin-left:-7px}.nk-avatar-group .mini-avatar:first-child,.nk-avatar-group .nk-avatar:first-child,.nk-avatar-group ::slotted(.mini-avatar:first-child),.nk-avatar-group ::slotted(.nk-avatar:first-child){margin-left:0}.nk-avatar-group .more,.nk-avatar-group ::slotted(.more){background:var(--nk-bg-callout);color:var(--nk-text-secondary)}.nk-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;height:24px;border-radius:50%;overflow:hidden;vertical-align:middle;font-size:10px;font-weight:600;line-height:1;color:var(--nk-on-accent);user-select:none;background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));object-fit:cover}.nk-avatar.small{width:20px;height:20px;font-size:9px}.nk-avatar.large{width:32px;height:32px;font-size:12px}.nk-avatar.xlarge{width:56px;height:56px;font-size:20px}.nk-avatar.square{border-radius:4px}.nk-avatar>img,.nk-avatar ::slotted(img){display:block;width:100%;height:100%;object-fit:cover}.nk-avatar.gray,.nk-calendar .cal-marks i.gray{background:var(--nk-color-gray)}.nk-avatar.brown,.nk-calendar .cal-marks i.brown{background:var(--nk-color-brown)}.nk-avatar.orange,.nk-calendar .cal-marks i.orange{background:var(--nk-color-orange)}.nk-avatar.yellow,.nk-calendar .cal-marks i.yellow{background:var(--nk-color-yellow)}.nk-avatar.green,.nk-calendar .cal-marks i.green{background:var(--nk-color-green)}.nk-avatar.blue,.nk-calendar .cal-marks i.blue{background:var(--nk-color-blue)}.nk-avatar.purple,.nk-calendar .cal-marks i.purple{background:var(--nk-color-purple)}.nk-avatar.pink,.nk-calendar .cal-marks i.pink{background:var(--nk-color-pink)}.nk-avatar.red,.nk-calendar .cal-marks i.red{background:var(--nk-color-red)}.nk-panels{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:12px;margin:12px 0}.nk-panel{display:flex;flex-direction:column;gap:6px;min-width:0;padding:14px 16px;border:1px solid var(--nk-border);border-radius:10px;background:var(--nk-bg-card);box-shadow:var(--nk-shadow-card);font-size:14px;line-height:1.5;color:inherit;text-decoration:none;text-align:left}:is(a,button).nk-panel{cursor:pointer;font-family:inherit;transition:border-color .15s,background .15s}:is(a,button).nk-panel:hover{border-color:var(--nk-border-strong)}.nk-panel>h3{font-size:14px;font-weight:600;line-height:1.4}.nk-panel ::slotted(h3){font-size:14px;font-weight:600;line-height:1.4;margin:0!important}.nk-panel>p{font-size:13px;color:var(--nk-text-secondary)}.nk-panel ::slotted(p){font-size:13px;color:var(--nk-text-secondary);margin:0!important}.nk-panel>.nk-cover{flex:none;height:64px;margin:-14px -16px 2px;border-radius:9px 9px 0 0}.nk-panel>.nk-page-icon{font-size:28px}.nk-panel>.nk-cover+.nk-page-icon{margin-top:-24px}.nk-skeleton{border-radius:5px;margin-bottom:10px;background:linear-gradient(90deg,var(--nk-bg-callout) 25%,var(--nk-bg-hover) 50%,var(--nk-bg-callout) 75%);background-size:200% 100%;animation:nk-shimmer 1.6s infinite}@keyframes nk-shimmer{to{background-position:-200% 0}}.nk-empty{text-align:center;padding:36px 20px;border:1.5px dashed var(--nk-border-strong);border-radius:10px;color:var(--nk-text-tertiary)}.nk-empty .e-icon,.nk-empty ::slotted(.e-icon),.nk-empty ::slotted([slot=\"icon\"]){font-size:30px;margin-bottom:8px}.nk-empty .e-title,.nk-empty ::slotted(.e-title),.nk-empty ::slotted([slot=\"title\"]){font-weight:500;color:var(--nk-text-secondary);margin-bottom:3px;font-size:14px}.nk-empty .e-desc,.nk-empty ::slotted(.e-desc),.nk-empty ::slotted([slot=\"desc\"]){font-size:13px;margin-bottom:12px}.nk-empty .e-actions,.nk-empty ::slotted(.e-actions){display:flex;flex-wrap:wrap;justify-content:center;gap:8px}.nk-steps{display:flex;flex-direction:column;margin:8px 0;padding:0;list-style:none;font-size:14px}.nk-step{position:relative;display:flex;align-items:flex-start;gap:10px;padding-bottom:14px;line-height:20px;color:var(--nk-text-tertiary)}.nk-step:last-child{padding-bottom:0}.nk-step:not(:last-child):after{content:\"\";position:absolute;left:10px;top:24px;bottom:4px;width:1px;background:var(--nk-border)}.nk-step .st-mark{flex:none;width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--nk-border-strong);background:var(--nk-bg);font-size:11px;font-weight:600;line-height:1}.nk-step .st-desc{display:block;font-size:12px;line-height:18px;color:var(--nk-text-tertiary);font-weight:400}.nk-step.done{color:var(--nk-text-secondary)}.nk-step.done .st-mark{background:var(--nk-tag-green-bg);color:var(--nk-tag-green-text);border-color:transparent}.nk-step.current{color:var(--nk-text);font-weight:500}.nk-step.current .st-mark{border-color:var(--nk-accent);color:var(--nk-accent)}.nk-comments{border-left:1px solid var(--nk-border);padding:4px 0 4px 18px;margin:8px 0 8px 8px}.nk-comment{display:flex;gap:9px;margin-bottom:14px}.nk-comment .mini-avatar,.nk-comment ::slotted(.mini-avatar),.nk-comment ::slotted([slot=\"avatar\"]){width:24px;height:24px;border-radius:50%;color:var(--nk-on-accent);flex-shrink:0;font-size:10px;font-weight:600;display:flex;align-items:center;justify-content:center}.nk-comment .c-head,.nk-comment ::slotted(.c-head){font-size:12px;color:var(--nk-text-tertiary);margin-bottom:2px}.nk-comment .c-head b{color:var(--nk-text);font-weight:600}.nk-comment .c-body,.nk-comment ::slotted(.c-body){font-size:14px;line-height:1.5}.nk-comment-input{display:flex;gap:8px;align-items:center;margin-top:4px}.nk-comment-input input{min-width:0;flex:1}.nk-ai-thread{display:flex;flex-direction:column;gap:14px}.nk-ai-msg{display:flex;gap:9px}.nk-ai-msg .mini-avatar,.nk-ai-msg ::slotted(.mini-avatar),.nk-ai-msg ::slotted([slot=\"avatar\"]){width:24px;height:24px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:12px;background:var(--nk-bg-callout)}.nk-ai-msg.user .mini-avatar,.nk-ai-msg.user ::slotted(.mini-avatar),.nk-ai-msg.user ::slotted([slot=\"avatar\"]){background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue));color:var(--nk-on-accent);font-size:9.5px;font-weight:600}.nk-ai-msg .a-body,.nk-ai-msg ::slotted(.a-body){font-size:14px;line-height:1.55;padding-top:2px}.nk-ai-msg .a-name,.nk-ai-msg ::slotted(.a-name){font-size:12px;font-weight:600;margin-bottom:2px}.nk-ai-msg .a-name span{color:var(--nk-text-tertiary);font-weight:400}.nk-ai-msg.user.bubble{justify-content:flex-end}.nk-ai-msg.bubble .a-body,.nk-ai-msg.bubble ::slotted(.a-body){max-width:85%;padding:6px 12px;border-radius:16px;background:var(--nk-bg-callout)}.nk-ai-actions{display:flex;gap:4px;margin-top:6px}.nk-ai-actions button{font-family:inherit;font-size:12px;color:var(--nk-text-secondary);background:transparent;border:1px solid var(--nk-border);border-radius:5px;padding:2px 8px;cursor:pointer}.nk-ai-actions ::slotted(button){font-family:inherit;font-size:12px;color:var(--nk-text-secondary);background:transparent;border:1px solid var(--nk-border);border-radius:5px;padding:2px 8px!important;cursor:pointer}.nk-ai-actions button:hover,.nk-ai-actions ::slotted(button:hover){background:var(--nk-bg-hover);color:var(--nk-text)}.nk-ai-input-row{display:flex;align-items:center;gap:8px;margin-top:14px;border:1px solid var(--nk-border-strong);border-radius:10px;padding:8px 12px}.nk-ai-input-row:focus-within{border-color:var(--nk-accent)}.nk-ai-input-row input{flex:1;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;color:var(--nk-text);min-width:0}.nk-ai-input-row input::placeholder{color:var(--nk-text-tertiary)}.nk-ai-send{border:none;background:var(--nk-accent);color:var(--nk-on-accent);border-radius:6px;width:26px;height:26px;cursor:pointer;font-size:13px;flex-shrink:0}.nk-block-host{position:relative;border-radius:var(--nk-radius);margin:8px 0;padding:2px 0 2px 2px;transition:background .15s,box-shadow .15s}.nk-block-host:hover{background:var(--nk-bg-hover)}.nk-block-host:focus-within{background:transparent;box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 25%,transparent)}.nk-block-host.nk-drop-target{box-shadow:0 -2px 0 0 var(--nk-accent);background:transparent}.nk-block-host .nk-block-handle,.nk-block-host ::slotted(.nk-block-handle){position:absolute;left:-26px;top:4px;width:18px;height:20px;border-radius:4px;display:flex;align-items:center;justify-content:center;color:var(--nk-text-tertiary);font-size:13px;cursor:grab;opacity:0;transition:opacity .15s;user-select:none}.nk-block-host:hover .nk-block-handle{opacity:1}.nk-block-host .nk-block-actions{position:absolute;display:flex;gap:1px;z-index:2;opacity:0;transition:opacity .15s;pointer-events:none}.nk-block-host .nk-block-actions.show{opacity:1;pointer-events:auto}.nk-block-host .nk-block-actions button,.nk-block-host .nk-block-actions ::slotted(button){width:20px;height:22px;padding:0;border:none;border-radius:4px;background:transparent;color:var(--nk-text-tertiary);font-family:inherit;font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}.nk-block-host .nk-block-actions button:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-block-host .nk-block-actions .drag{cursor:grab}.nk-block-host .nk-block-actions .drag:active{cursor:grabbing}.nk-prose,.nk-block-host .ProseMirror{font-family:var(--nk-font);line-height:1.5;color:var(--nk-text);overflow-wrap:break-word}.nk-block-host .ProseMirror{outline:none;min-height:60px;padding:4px 2px}.nk-prose>*+*,.nk-block-host .ProseMirror>*+*{margin-top:6px}.nk-prose h1,.nk-block-host .ProseMirror h1{font-size:1.875em;font-weight:600;line-height:1.3;letter-spacing:-.01em;margin:32px 0 4px}.nk-prose h2,.nk-block-host .ProseMirror h2{font-size:1.5em;font-weight:600;line-height:1.3;margin:24px 0 4px}.nk-prose h3,.nk-block-host .ProseMirror h3{font-size:1.25em;font-weight:600;line-height:1.3;margin:16px 0 2px}.nk-prose :is(h4,h5,h6),.nk-block-host .ProseMirror :is(h4,h5,h6){font-size:1em;font-weight:600;margin:12px 0 0}.nk-prose>:first-child,.nk-block-host .ProseMirror>:first-child{margin-top:0}.nk-prose>:last-child,.nk-block-host .ProseMirror>:last-child{margin-bottom:0}.nk-prose p:empty:before{content:\"\";display:inline-block}.nk-prose :is(strong,b),.nk-block-host .ProseMirror :is(strong,b){font-weight:600}.nk-prose :is(ul,ol),.nk-block-host .ProseMirror :is(ul,ol){padding-left:24px;margin:4px 0}.nk-prose ul,.nk-block-host .ProseMirror ul{list-style:disc}.nk-prose ol,.nk-block-host .ProseMirror ol{list-style:decimal}.nk-prose li,.nk-block-host .ProseMirror li{margin:2px 0}.nk-prose li::marker,.nk-block-host .ProseMirror li::marker{color:var(--nk-text-tertiary)}.nk-prose ul[data-type=taskList],.nk-block-host .ProseMirror ul[data-type=taskList]{list-style:none;padding-left:2px}.nk-prose ul[data-type=taskList] li,.nk-block-host .ProseMirror ul[data-type=taskList] li{display:flex;gap:8px;align-items:flex-start}.nk-prose ul[data-type=taskList] li>label,.nk-block-host .ProseMirror ul[data-type=taskList] li>label{flex-shrink:0;margin-top:max(0px,calc((1lh - 16px)/2));user-select:none}.nk-prose ul[data-type=taskList] li>div,.nk-block-host .ProseMirror ul[data-type=taskList] li>div{flex:1;min-width:0}.nk-prose ul[data-type=taskList] input[type=checkbox],.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]{appearance:none;width:16px;height:16px;margin:0;border:1.4px solid var(--nk-border-strong);border-radius:2px;cursor:pointer;position:relative;background:var(--nk-bg);display:block}.nk-prose ul[data-type=taskList] input[type=checkbox]:checked,.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]:checked{background:var(--nk-accent);border-color:var(--nk-accent)}.nk-prose ul[data-type=taskList] input[type=checkbox]:checked:after,.nk-block-host .ProseMirror ul[data-type=taskList] input[type=checkbox]:checked:after{content:\"\\2713\";color:var(--nk-on-accent);font-size:11px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.nk-prose li[data-checked=true]>div,.nk-block-host .ProseMirror li[data-checked=true]>div{text-decoration:line-through;color:var(--nk-text-tertiary)}.nk-prose blockquote,.nk-block-host .ProseMirror blockquote{border-left:3px solid var(--nk-text);padding:2px 0 2px 14px;margin:12px 0;color:var(--nk-text-secondary)}.nk-prose code,.nk-block-host .ProseMirror code{font-family:var(--nk-font-mono);font-size:85%;color:var(--nk-danger);background:color-mix(in srgb,var(--nk-danger) 8%,transparent);border-radius:4px;padding:1px 5px}.nk-prose pre,.nk-block-host .ProseMirror pre{background:var(--nk-bg-code);border:1px solid var(--nk-border);border-radius:var(--nk-radius);padding:16px 20px;margin:12px 0;font-family:var(--nk-font-mono);font-size:13px;line-height:1.6;color:var(--nk-text-secondary);overflow-x:auto}.nk-prose pre code,.nk-block-host .ProseMirror pre code{background:none;color:inherit;padding:0;font-size:inherit}.nk-prose hr,.nk-block-host .ProseMirror hr{border:none;border-top:1px solid var(--nk-border);margin:20px 0}.nk-prose a,.nk-block-host .ProseMirror a{color:var(--nk-accent);text-decoration:underline;text-underline-offset:2px}.nk-prose img{max-width:100%;height:auto}.nk-prose table{display:block;width:max-content;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:14px;margin:12px 0}.nk-prose :is(th,td){padding:6px 10px;border:1px solid var(--nk-border);text-align:left;vertical-align:top}.nk-prose th{font-weight:600}.nk-block-host .ProseMirror-gapcursor:after{border-top-color:var(--nk-text)}.nk-block-host .ProseMirror .ProseMirror-selectednode{background:color-mix(in srgb,var(--nk-accent) 8%,transparent)}.nk-block-host .ProseMirror-selectednode{box-shadow:0 0 0 2px color-mix(in srgb,var(--nk-accent) 35%,transparent);border-radius:3px}.nk-block-host .ProseMirror ::selection{background:color-mix(in srgb,var(--nk-accent) 25%,transparent)}.nk-block-host .ProseMirror p.is-editor-empty:first-child:before,.nk-block-host .ProseMirror .is-empty:before{content:attr(data-placeholder);color:var(--nk-text-tertiary);float:left;height:0;pointer-events:none}.nk-block-host .bn-container{font-family:var(--nk-font);color:var(--nk-text);background:transparent}.nk-block-host .bn-editor{padding:4px 2px}.nk-block-host .bn-block-content{font-size:14px;line-height:1.6}.nk-block-host .bn-side-menu{color:var(--nk-text-tertiary)}.nk-block-host .bn-drag-handle{border-radius:4px}.nk-block-host .bn-drag-handle:hover{background:var(--nk-bg-hover)}.nk-block-host .novel-editor{font-family:var(--nk-font);color:var(--nk-text)}.nk-block-host .novel-prose{max-width:none}.nk-slash-menu,.nk-block-host .bn-suggestion-menu,.nk-block-host .tippy-box{background:var(--nk-bg);border-radius:10px;box-shadow:var(--nk-shadow-menu);padding:6px;width:280px;max-height:320px;overflow-y:auto;font-family:var(--nk-font);font-size:14px;color:var(--nk-text)}.nk-slash-menu-label{font-size:12px;color:var(--nk-text-tertiary);padding:6px 9px 2px}.nk-slash-item{display:flex;align-items:center;gap:10px;padding:6px 9px;border-radius:5px;cursor:pointer;user-select:none}.nk-slash-item:hover,.nk-slash-item.selected{background:var(--nk-bg-hover)}.nk-slash-item .m-icon,.nk-slash-item ::slotted(.m-icon){width:28px;height:28px;flex-shrink:0;border-radius:4px;background:var(--nk-bg-callout);border:1px solid var(--nk-border);display:flex;align-items:center;justify-content:center;font-size:15px}.nk-slash-item .m-desc{font-size:12px;color:var(--nk-text-tertiary)}.nk-bubble-menu{display:flex;align-items:center;gap:2px;background:var(--nk-bg);border-radius:8px;box-shadow:var(--nk-shadow-menu);padding:4px}.nk-bubble-menu button{font-family:inherit;font-size:13px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 8px;border-radius:5px;cursor:pointer}.nk-bubble-menu ::slotted(button){font-family:inherit;font-size:13px;border:none;background:transparent;color:var(--nk-text-secondary);padding:4px 8px!important;border-radius:5px;cursor:pointer}.nk-bubble-menu button:hover,.nk-bubble-menu ::slotted(button:hover){background:var(--nk-bg-hover);color:var(--nk-text)}.nk-bubble-menu button.active,.nk-bubble-menu ::slotted(button.active){color:var(--nk-accent)}@media(max-width:860px){.nk-sidebar{display:none;position:fixed;inset:0 auto 0 0;z-index:60;transform:translate(-100%);transition:background .25s ease,transform .24s cubic-bezier(.2,.8,.25,1),display .24s allow-discrete}.nk-sidebar.open{display:flex;transform:none}@starting-style{.nk-sidebar.open{transform:translate(-100%)}}.nk-sidebar-backdrop{opacity:0;transition:opacity .24s ease,display .24s allow-discrete}.nk-sidebar-backdrop.open{display:block;opacity:1}@starting-style{.nk-sidebar-backdrop.open{opacity:0}}.nk-sidebar-toggle{display:inline-flex}.nk-tab-bar{display:flex}.nk-tab-bar.fixed+.nk-tab-bar-spacer{display:block}.nk-page{padding-left:max(24px,env(safe-area-inset-left,0px));padding-right:max(24px,env(safe-area-inset-right,0px));padding-bottom:80px}.nk-settings-nav{width:60px;min-width:60px}.nk-settings-nav .label,.nk-settings-nav .nk-section-label,.nk-settings-user .u-text{display:none}.nk-settings-content{padding:24px}.nk-cmdk-backdrop{padding-top:max(6vh,env(safe-area-inset-top,0px))}.nk-cmdk{width:min(560px,96vw)}.nk-stats{flex-wrap:wrap}.nk-breadcrumb{min-width:0}.nk-breadcrumb>.crumb:not(:last-child),.nk-breadcrumb ::slotted(.crumb:not(:last-child)),.nk-breadcrumb>.sep,.nk-breadcrumb ::slotted(.sep),.nk-topbar-meta,.nk-topbar-actions ::slotted(.nk-topbar-meta){display:none}.nk-breadcrumb>.crumb:last-child,.nk-breadcrumb ::slotted(.crumb:last-child){display:block;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nk-topbar-actions{flex-shrink:0}.nk-field{flex-wrap:wrap;row-gap:6px}.nk-field .f-control,.nk-field ::slotted(.f-control){max-width:100%;min-width:0}.nk-input,.nk-select,.nk-textarea,.nk-slider{max-width:100%}.nk-prop{flex-direction:column;align-items:stretch}.nk-prop .p-name{flex:none;min-height:26px}.nk-prop .p-value{min-height:30px;padding:3px 6px 7px}.nk-pop.sheet{position:fixed!important;inset:auto 0 0!important;width:auto!important;transform:none!important;z-index:100;--_nk-row: 40px;max-height:85dvh;overflow-y:auto;overscroll-behavior:contain;border-radius:14px 14px 0 0;padding:6px max(8px,env(safe-area-inset-right,0px)) max(12px,env(safe-area-inset-bottom,0px)) max(8px,env(safe-area-inset-left,0px));box-shadow:0 0 0 100vmax var(--nk-scrim-soft),var(--nk-shadow-menu)}.nk-pop.sheet:before{content:\"\";display:block;width:36px;height:4px;margin:4px auto 8px;border-radius:2px;background:var(--nk-border-strong)}.nk-pop.sheet.floating{translate:0 100%;transition:opacity .2s ease,translate .25s cubic-bezier(.2,.8,.2,1),visibility 0s linear .25s}.nk-pop.sheet.floating.open{translate:0 0;transition:opacity .2s ease,translate .25s cubic-bezier(.2,.8,.2,1),visibility 0s}.nk-pop.sheet,.nk-sheet{--_nk-cell: 44px}.nk-calendar-view .cv-day{min-height:64px;padding:2px 2px 4px}.nk-calendar-view .cv-item{padding:1px 4px;font-size:11px;line-height:16px}.nk-peek-backdrop{pointer-events:auto}.nk-peek-backdrop.open{background-color:var(--nk-scrim-soft)}@starting-style{.nk-peek-backdrop.open{background-color:transparent}}.nk-peek{--_nk-title: 28px;top:auto;left:0;width:auto;max-height:92dvh;border-radius:14px 14px 0 0;translate:0 100%}.nk-peek-backdrop.open .nk-peek{translate:0 0}@starting-style{.nk-peek-backdrop.open .nk-peek{translate:0 100%}}.nk-peek:before{content:\"\";flex:none;width:36px;height:4px;margin:10px auto 0;border-radius:2px;background:var(--nk-border-strong)}.nk-peek .pk-bar{height:40px;padding:0 max(8px,env(safe-area-inset-right,0px)) 0 max(8px,env(safe-area-inset-left,0px))}.nk-peek .pk-body{padding:0 max(20px,env(safe-area-inset-right,0px)) max(24px,env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px))}:root:has(.nk-tab-bar:not([hidden])) .nk-toast{bottom:calc(var(--nk-tab-bar-height) + max(6px,env(safe-area-inset-bottom,0px)) + 6px)}:root:has(.nk-tab-bar.floating:not([hidden])) .nk-toast{bottom:calc(var(--nk-tab-bar-height) + 24px + env(safe-area-inset-bottom,0px))}}@media(prefers-reduced-motion:reduce){.nk-skeleton{animation:none;background:var(--nk-bg-callout)}[class*=nk-],[class*=nk-]:before,[class*=nk-]:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}\n/*# sourceMappingURL=notionkit.min.css.map */\n";
|
|
10
10
|
|
|
11
11
|
const componentsCss = componentsHead + componentsTail;
|
|
12
12
|
const css = componentsHead + tokensCss + componentsTail;
|
|
@@ -3909,6 +3909,834 @@ class NkSteps extends NkElement {
|
|
|
3909
3909
|
|
|
3910
3910
|
customElements.define('nk-steps', NkSteps);
|
|
3911
3911
|
|
|
3912
|
+
// <nk-bookmark href="https://notionkit.jungherz.com" title="NotionKit" desc="…"
|
|
3913
|
+
// favicon="favicon.svg" cover="og.jpg"></nk-bookmark>
|
|
3914
|
+
// → <a class="nk-bookmark" href="…" target="_blank" rel="noopener">
|
|
3915
|
+
// <span class="bm-text"><span class="bm-title">…</span><span class="bm-desc">…</span>
|
|
3916
|
+
// <span class="bm-url"><img class="bm-favicon"><span>…</span></span></span>
|
|
3917
|
+
// <span class="bm-cover"><img></span></a>
|
|
3918
|
+
// Notion's link block (NotionKit 1.8.0), filled from what you know of the
|
|
3919
|
+
// page: og:title, og:description, og:image. `title` is the heading, never a
|
|
3920
|
+
// tooltip – see NkElement.takeTitle(); without it the host name stands in.
|
|
3921
|
+
// The address shown is `href`, or `url` where it should read differently. A
|
|
3922
|
+
// part without a value is left out, not hidden – the stylesheet gives the
|
|
3923
|
+
// description its own display. Opens in a new tab unless `target` says so.
|
|
3924
|
+
class NkBookmark extends NkElement {
|
|
3925
|
+
static get observedAttributes() { return ['href', 'title', 'desc', 'favicon', 'cover', 'target', 'url']; }
|
|
3926
|
+
|
|
3927
|
+
render() {
|
|
3928
|
+
this.takeTitle();
|
|
3929
|
+
this._a = this.createElement('a', ['nk-bookmark']);
|
|
3930
|
+
this._wrapper.appendChild(this._a);
|
|
3931
|
+
this._sync();
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
_sync() {
|
|
3935
|
+
if (!this._a) return;
|
|
3936
|
+
const href = this.getAttribute('href') || '';
|
|
3937
|
+
this._a.setAttribute('href', href);
|
|
3938
|
+
const target = this.getAttribute('target') || '_blank';
|
|
3939
|
+
this._a.setAttribute('target', target);
|
|
3940
|
+
if (target === '_blank') this._a.setAttribute('rel', 'noopener'); else this._a.removeAttribute('rel');
|
|
3941
|
+
let host = href;
|
|
3942
|
+
try { host = new URL(href, location.href).host; } catch { /* keep the text */ }
|
|
3943
|
+
|
|
3944
|
+
const text = this.createElement('span', ['bm-text']);
|
|
3945
|
+
const title = this.createElement('span', ['bm-title']);
|
|
3946
|
+
title.textContent = this._titleText || host;
|
|
3947
|
+
text.appendChild(title);
|
|
3948
|
+
const desc = this.getAttribute('desc');
|
|
3949
|
+
if (desc) { const d = this.createElement('span', ['bm-desc']); d.textContent = desc; text.appendChild(d); }
|
|
3950
|
+
const url = this.createElement('span', ['bm-url']);
|
|
3951
|
+
const favicon = this.getAttribute('favicon');
|
|
3952
|
+
if (favicon) url.appendChild(this.createElement('img', ['bm-favicon'], { src: favicon, alt: '' }));
|
|
3953
|
+
const address = document.createElement('span');
|
|
3954
|
+
address.textContent = this.getAttribute('url') || href;
|
|
3955
|
+
url.appendChild(address);
|
|
3956
|
+
text.appendChild(url);
|
|
3957
|
+
const parts = [text];
|
|
3958
|
+
const cover = this.getAttribute('cover');
|
|
3959
|
+
if (cover) { const c = this.createElement('span', ['bm-cover']); c.appendChild(this.createElement('img', [], { src: cover, alt: '' })); parts.push(c); }
|
|
3960
|
+
this._a.replaceChildren(...parts);
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
onAttributeChanged(name, _old, value) {
|
|
3964
|
+
if (name === 'title' && !this.takeTitle(value)) return;
|
|
3965
|
+
this._sync();
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
focus(o) { this._a?.focus(o); }
|
|
3969
|
+
get title() { return this._titleText ?? ''; }
|
|
3970
|
+
set title(v) { this._titleText = v == null ? '' : String(v); this._sync(); }
|
|
3971
|
+
get href() { return this.getAttribute('href') || ''; }
|
|
3972
|
+
set href(v) { this.setAttribute('href', v); }
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
customElements.define('nk-bookmark', NkBookmark);
|
|
3976
|
+
|
|
3977
|
+
// <nk-copy-field value="https://monahilft.notionkit.app"></nk-copy-field>
|
|
3978
|
+
// <nk-copy-field value="ntn_4f2…" secret mono></nk-copy-field>
|
|
3979
|
+
// → <div class="nk-copy-field mono"><span class="cf-value">…</span>
|
|
3980
|
+
// <button class="cf-btn">Show</button><button class="cf-btn">Copy</button></div>
|
|
3981
|
+
// A value to take along – a link, an address, a key (NotionKit 1.8.0). Copy
|
|
3982
|
+
// writes it to the clipboard and says "Copied" in green for a moment; where
|
|
3983
|
+
// the clipboard is not allowed, the value is shown and selected instead, for
|
|
3984
|
+
// ⌘C. `secret` masks it behind a Show/Hide toggle; Copy still copies the
|
|
3985
|
+
// real value. `value` set as a property is not reflected, so a key never
|
|
3986
|
+
// lands in the markup. Fires nk-action { action: 'copy', value, ok }. The
|
|
3987
|
+
// texts are attributes: copy-label, copied-label, show-label, hide-label.
|
|
3988
|
+
class NkCopyField extends NkElement {
|
|
3989
|
+
static get observedAttributes() { return ['value', 'mono', 'wrap', 'wide', 'secret', 'copy-label', 'copied-label', 'show-label', 'hide-label']; }
|
|
3990
|
+
|
|
3991
|
+
render() {
|
|
3992
|
+
this._val ??= this.getAttribute('value') ?? '';
|
|
3993
|
+
this._box = this.createElement('div', ['nk-copy-field']);
|
|
3994
|
+
this._text = this.createElement('span', ['cf-value']);
|
|
3995
|
+
this._show = this.createElement('button', ['cf-btn'], { type: 'button' });
|
|
3996
|
+
this._copy = this.createElement('button', ['cf-btn'], { type: 'button' });
|
|
3997
|
+
this._box.append(this._text, this._copy);
|
|
3998
|
+
this._wrapper.appendChild(this._box);
|
|
3999
|
+
this._sync();
|
|
4000
|
+
}
|
|
4001
|
+
|
|
4002
|
+
_sync() {
|
|
4003
|
+
if (!this._box) return;
|
|
4004
|
+
for (const m of ['mono', 'wrap', 'wide']) this._box.classList.toggle(m, this.getBoolAttr(m));
|
|
4005
|
+
const secret = this.getBoolAttr('secret');
|
|
4006
|
+
this._text.textContent = secret && !this._revealed ? '•'.repeat(Math.min(this._val.length, 24)) : this._val;
|
|
4007
|
+
// Not `hidden`: .cf-btn sets no display of its own that could lose to it,
|
|
4008
|
+
// but a button that is not there cannot be tabbed to either.
|
|
4009
|
+
if (secret && !this._show.isConnected) this._copy.before(this._show);
|
|
4010
|
+
if (!secret) this._show.remove();
|
|
4011
|
+
this._show.textContent = this._revealed ? (this.getAttribute('hide-label') || 'Hide') : (this.getAttribute('show-label') || 'Show');
|
|
4012
|
+
this._show.setAttribute('aria-pressed', String(!!this._revealed));
|
|
4013
|
+
this._copy.textContent = this._copied ? (this.getAttribute('copied-label') || 'Copied') : (this.getAttribute('copy-label') || 'Copy');
|
|
4014
|
+
this._copy.classList.toggle('copied', !!this._copied);
|
|
4015
|
+
}
|
|
4016
|
+
|
|
4017
|
+
setupEvents() {
|
|
4018
|
+
this._onCopy = () => this.copy();
|
|
4019
|
+
this._onShow = () => { this._revealed = !this._revealed; this._sync(); };
|
|
4020
|
+
this._copy.addEventListener('click', this._onCopy);
|
|
4021
|
+
this._show.addEventListener('click', this._onShow);
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
teardownEvents() {
|
|
4025
|
+
this._copy?.removeEventListener('click', this._onCopy);
|
|
4026
|
+
this._show?.removeEventListener('click', this._onShow);
|
|
4027
|
+
clearTimeout(this._timer);
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
onAttributeChanged(name, _old, value) {
|
|
4031
|
+
if (name === 'value') this._val = value ?? '';
|
|
4032
|
+
this._sync();
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
/** Copies the value; resolves to whether the clipboard took it. */
|
|
4036
|
+
async copy() {
|
|
4037
|
+
const value = this._val;
|
|
4038
|
+
let ok = true;
|
|
4039
|
+
try { await navigator.clipboard.writeText(value); } catch { ok = false; }
|
|
4040
|
+
if (ok) {
|
|
4041
|
+
this._copied = true;
|
|
4042
|
+
clearTimeout(this._timer);
|
|
4043
|
+
this._timer = setTimeout(() => { this._copied = false; this._sync(); }, 1500);
|
|
4044
|
+
} else {
|
|
4045
|
+
this._revealed = true;
|
|
4046
|
+
}
|
|
4047
|
+
this._sync();
|
|
4048
|
+
if (!ok) getSelection()?.selectAllChildren(this._text);
|
|
4049
|
+
this.emit('nk-action', { action: 'copy', value, ok });
|
|
4050
|
+
return ok;
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
get value() { return this._val ?? this.getAttribute('value') ?? ''; }
|
|
4054
|
+
set value(v) { this._val = v == null ? '' : String(v); this._sync(); }
|
|
4055
|
+
get secret() { return this.getBoolAttr('secret'); }
|
|
4056
|
+
set secret(v) { this.setBoolAttr('secret', v); }
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
customElements.define('nk-copy-field', NkCopyField);
|
|
4060
|
+
|
|
4061
|
+
// <nk-image-picker initials="MK" label="Profile picture"></nk-image-picker>
|
|
4062
|
+
// <nk-image-picker square initials="M" max="256" type="image/png"></nk-image-picker>
|
|
4063
|
+
// → <div class="nk-profile-row"><div class="big-avatar">MK | <img></div>
|
|
4064
|
+
// <div class="pr-actions"><button class="nk-btn secondary small">Upload image</button>
|
|
4065
|
+
// <button class="nk-btn secondary small pr-remove">Remove</button><input type="file" hidden></div></div>
|
|
4066
|
+
//
|
|
4067
|
+
// A picture for a person or a workspace (NotionKit 1.8.0): the profile row
|
|
4068
|
+
// with its actions, round – or `square`, a workspace icon. Ported from
|
|
4069
|
+
// GlassKit Elements' glk-image-picker: the file goes through
|
|
4070
|
+
// createImageBitmap with imageOrientation 'from-image' – the EXIF rotation
|
|
4071
|
+
// of a phone photo without a library – onto a canvas no larger than `max`
|
|
4072
|
+
// (default 512), out as `type` (default image/jpeg, on white; image/png
|
|
4073
|
+
// keeps transparency) at `quality` (0.82). The file input is hidden and
|
|
4074
|
+
// opened from a real button, and cleared after every pick, so the same file
|
|
4075
|
+
// can be chosen again. Not form-associated: listen to nk-change and upload
|
|
4076
|
+
// the data URL. `src` set as a property is not reflected, so megabytes of
|
|
4077
|
+
// data URL never land in the DOM.
|
|
4078
|
+
// Events: nk-change { dataUrl, width, height, size } after a pick, and on
|
|
4079
|
+
// remove with an empty dataUrl; nk-error { message, name } when the
|
|
4080
|
+
// file cannot be decoded (HEIC outside Safari, a broken file).
|
|
4081
|
+
// Texts: choose-label, change-label, remove-label; label names the group.
|
|
4082
|
+
|
|
4083
|
+
function dataUrlBytes(url) {
|
|
4084
|
+
const b64 = url.slice(url.indexOf(',') + 1);
|
|
4085
|
+
const padding = b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0;
|
|
4086
|
+
return Math.floor((b64.length * 3) / 4) - padding;
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4089
|
+
class NkImagePicker extends NkElement {
|
|
4090
|
+
static get observedAttributes() { return ['src', 'initials', 'square', 'label', 'max', 'type', 'quality', 'accept', 'choose-label', 'change-label', 'remove-label']; }
|
|
4091
|
+
|
|
4092
|
+
render() {
|
|
4093
|
+
this._src ??= this.getAttribute('src') || '';
|
|
4094
|
+
this._row = this.createElement('div', ['nk-profile-row'], { role: 'group' });
|
|
4095
|
+
this._avatar = this.createElement('div', ['big-avatar']);
|
|
4096
|
+
const actions = this.createElement('div', ['pr-actions']);
|
|
4097
|
+
this._choose = this.createElement('button', ['nk-btn', 'secondary', 'small'], { type: 'button' });
|
|
4098
|
+
this._remove = this.createElement('button', ['nk-btn', 'secondary', 'small', 'pr-remove'], { type: 'button' });
|
|
4099
|
+
this._input = this.createElement('input', [], { type: 'file', tabindex: '-1' });
|
|
4100
|
+
this._input.hidden = true;
|
|
4101
|
+
actions.append(this._choose, this._remove, this._input);
|
|
4102
|
+
this._row.append(this._avatar, actions);
|
|
4103
|
+
this._wrapper.appendChild(this._row);
|
|
4104
|
+
this._sync();
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
get _max() { return Math.max(1, Math.floor(Number(this.getAttribute('max'))) || 512); }
|
|
4108
|
+
get _type() { return this.getAttribute('type') || 'image/jpeg'; }
|
|
4109
|
+
get _quality() { const q = Number(this.getAttribute('quality')); return this.hasAttribute('quality') && q >= 0 && q <= 1 ? q : 0.82; }
|
|
4110
|
+
|
|
4111
|
+
_sync() {
|
|
4112
|
+
if (!this._row) return;
|
|
4113
|
+
this._avatar.classList.toggle('square', this.getBoolAttr('square'));
|
|
4114
|
+
if (!this._src) {
|
|
4115
|
+
this._img = null;
|
|
4116
|
+
this._avatar.textContent = this.getAttribute('initials') || '';
|
|
4117
|
+
} else if (!this._img || this._img.getAttribute('src') !== this._src) {
|
|
4118
|
+
this._img = this.createElement('img', [], { src: this._src, alt: '' });
|
|
4119
|
+
this._avatar.replaceChildren(this._img);
|
|
4120
|
+
}
|
|
4121
|
+
const label = this.getAttribute('label');
|
|
4122
|
+
if (label) this._row.setAttribute('aria-label', label); else this._row.removeAttribute('aria-label');
|
|
4123
|
+
this._choose.textContent = this._src ? (this.getAttribute('change-label') || 'Change image') : (this.getAttribute('choose-label') || 'Upload image');
|
|
4124
|
+
this._remove.textContent = this.getAttribute('remove-label') || 'Remove';
|
|
4125
|
+
this._remove.hidden = !this._src;
|
|
4126
|
+
this._input.accept = this.getAttribute('accept') || 'image/*';
|
|
4127
|
+
}
|
|
4128
|
+
|
|
4129
|
+
async _pick(file) {
|
|
4130
|
+
if (!file) return;
|
|
4131
|
+
try {
|
|
4132
|
+
const bitmap = await createImageBitmap(file, { imageOrientation: 'from-image' });
|
|
4133
|
+
const scale = Math.min(1, this._max / Math.max(bitmap.width, bitmap.height));
|
|
4134
|
+
const canvas = document.createElement('canvas');
|
|
4135
|
+
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
|
|
4136
|
+
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
|
|
4137
|
+
const ctx = canvas.getContext('2d');
|
|
4138
|
+
if (this._type === 'image/jpeg') {
|
|
4139
|
+
// JPEG has no alpha; without this a transparent PNG comes out on black.
|
|
4140
|
+
ctx.fillStyle = '#fff';
|
|
4141
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
4142
|
+
}
|
|
4143
|
+
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
|
|
4144
|
+
bitmap.close();
|
|
4145
|
+
const dataUrl = canvas.toDataURL(this._type, this._quality);
|
|
4146
|
+
this.src = dataUrl;
|
|
4147
|
+
this.emit('nk-change', { dataUrl, width: canvas.width, height: canvas.height, size: dataUrlBytes(dataUrl) });
|
|
4148
|
+
} catch (error) {
|
|
4149
|
+
this.emit('nk-error', { message: error?.message || String(error), name: file.name });
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
setupEvents() {
|
|
4154
|
+
this._onChoose = () => this._input.click();
|
|
4155
|
+
this._onChange = (e) => { const file = e.target.files?.[0]; e.target.value = ''; this._pick(file); };
|
|
4156
|
+
this._onRemove = () => {
|
|
4157
|
+
this.src = '';
|
|
4158
|
+
this._choose.focus(); // the remove button just went away under the focus
|
|
4159
|
+
this.emit('nk-change', { dataUrl: '', width: 0, height: 0, size: 0 });
|
|
4160
|
+
};
|
|
4161
|
+
this._choose.addEventListener('click', this._onChoose);
|
|
4162
|
+
this._input.addEventListener('change', this._onChange);
|
|
4163
|
+
this._remove.addEventListener('click', this._onRemove);
|
|
4164
|
+
}
|
|
4165
|
+
|
|
4166
|
+
teardownEvents() {
|
|
4167
|
+
this._choose?.removeEventListener('click', this._onChoose);
|
|
4168
|
+
this._input?.removeEventListener('change', this._onChange);
|
|
4169
|
+
this._remove?.removeEventListener('click', this._onRemove);
|
|
4170
|
+
}
|
|
4171
|
+
|
|
4172
|
+
onAttributeChanged(name, _old, value) {
|
|
4173
|
+
if (name === 'src') this._src = value || '';
|
|
4174
|
+
this._sync();
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
/** Opens the file dialog, as the button does. */
|
|
4178
|
+
choose() { this._input?.click(); }
|
|
4179
|
+
get src() { return this._src ?? this.getAttribute('src') ?? ''; }
|
|
4180
|
+
set src(v) { this._src = v || ''; this._sync(); }
|
|
4181
|
+
get square() { return this.getBoolAttr('square'); }
|
|
4182
|
+
set square(v) { this.setBoolAttr('square', v); }
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
customElements.define('nk-image-picker', NkImagePicker);
|
|
4186
|
+
|
|
4187
|
+
// Calendar days for nk-calendar and nk-calendar-view: local days as
|
|
4188
|
+
// 'YYYY-MM-DD', no library. Weeks are ISO weeks (Monday-based, the week with
|
|
4189
|
+
// the year's first Thursday); the first weekday comes from the locale.
|
|
4190
|
+
const pad = n => String(n).padStart(2, '0');
|
|
4191
|
+
|
|
4192
|
+
const isoOf = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
4193
|
+
const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
4194
|
+
|
|
4195
|
+
/** 'YYYY-MM-DD[THH:MM]', 'D.M.YYYY', a Date or { start } → a local Date at midnight, or null. */
|
|
4196
|
+
function parseDay(v) {
|
|
4197
|
+
if (v instanceof Date) return Number.isNaN(v.getTime()) ? null : new Date(v.getFullYear(), v.getMonth(), v.getDate());
|
|
4198
|
+
if (v && typeof v === 'object') return v.start ? parseDay(v.start) : null;
|
|
4199
|
+
const s = String(v ?? '').trim();
|
|
4200
|
+
let m = s.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
|
4201
|
+
if (m) return new Date(+m[1], +m[2] - 1, +m[3]);
|
|
4202
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
|
|
4203
|
+
return m ? new Date(+m[3], +m[2] - 1, +m[1]) : null;
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
function isoWeek(d) {
|
|
4207
|
+
const t = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
|
4208
|
+
t.setUTCDate(t.getUTCDate() + 4 - (t.getUTCDay() || 7));
|
|
4209
|
+
return Math.ceil(((t - Date.UTC(t.getUTCFullYear(), 0, 1)) / 864e5 + 1) / 7);
|
|
4210
|
+
}
|
|
4211
|
+
|
|
4212
|
+
/** The page's language unless the element names one. */
|
|
4213
|
+
const resolveLocale = attr => attr || document.documentElement.lang || navigator.language || 'en';
|
|
4214
|
+
|
|
4215
|
+
/** 0 = Sunday … 6 = Saturday, from Intl.Locale's week info; Monday where the browser cannot say. */
|
|
4216
|
+
function firstWeekday(locale) {
|
|
4217
|
+
try {
|
|
4218
|
+
const l = new Intl.Locale(locale), info = l.getWeekInfo?.() ?? l.weekInfo;
|
|
4219
|
+
if (info?.firstDay) return info.firstDay % 7;
|
|
4220
|
+
} catch { /* an unknown tag */ }
|
|
4221
|
+
return 1;
|
|
4222
|
+
}
|
|
4223
|
+
|
|
4224
|
+
/** Short weekday names from `weekStart` on; `length` cuts them (2 → "Mo"). */
|
|
4225
|
+
function weekdayNames(locale, weekStart, length = 0) {
|
|
4226
|
+
const f = new Intl.DateTimeFormat(locale, { weekday: 'short' });
|
|
4227
|
+
// 7 June 2026 is a Sunday, so 7 + n is weekday n.
|
|
4228
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
4229
|
+
const name = f.format(new Date(2026, 5, 7 + ((weekStart + i) % 7))).replace('.', '');
|
|
4230
|
+
return length ? name.slice(0, length) : name;
|
|
4231
|
+
});
|
|
4232
|
+
}
|
|
4233
|
+
|
|
4234
|
+
/** A month from its week start: `first`, `day(i)` for the i-th cell, the `rows` it needs. */
|
|
4235
|
+
function monthGrid(month, weekStart) {
|
|
4236
|
+
const [y, m] = month.split('-').map(Number), first = new Date(y, m - 1, 1), offset = (first.getDay() - weekStart + 7) % 7;
|
|
4237
|
+
return { m, first, day: i => new Date(y, m - 1, 1 - offset + i), rows: Math.ceil((offset + new Date(y, m, 0).getDate()) / 7) };
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
function stepMonth(month, n) {
|
|
4241
|
+
const [y, m] = month.split('-').map(Number);
|
|
4242
|
+
return isoOf(new Date(y, m - 1 + n, 1)).slice(0, 7);
|
|
4243
|
+
}
|
|
4244
|
+
|
|
4245
|
+
/** "KW" for German, "W" elsewhere – the head of the week column. */
|
|
4246
|
+
const weekLabel = locale => (/^de\b/i.test(locale) ? 'KW' : 'W');
|
|
4247
|
+
|
|
4248
|
+
const CHEVRONS = {
|
|
4249
|
+
prev: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg>',
|
|
4250
|
+
next: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>',
|
|
4251
|
+
};
|
|
4252
|
+
|
|
4253
|
+
// Placement for elements that float over the page – <nk-menu floating>,
|
|
4254
|
+
// <nk-calendar floating>: the host is a fixed box put under its anchor.
|
|
4255
|
+
|
|
4256
|
+
/** The border box of an element, or of the first descendant with one (display: contents hosts). */
|
|
4257
|
+
function boxOf(el) {
|
|
4258
|
+
if (el.getClientRects().length) return el.getBoundingClientRect();
|
|
4259
|
+
for (const child of [...(el.shadowRoot?.children ?? []), ...el.children]) {
|
|
4260
|
+
const r = boxOf(child);
|
|
4261
|
+
if (r.width || r.height) return r;
|
|
4262
|
+
}
|
|
4263
|
+
return el.getBoundingClientRect();
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
/** Puts `host` 6px under `anchor`, right edges aligned – left edges with align="start". */
|
|
4267
|
+
function placeUnder(host, anchor, align) {
|
|
4268
|
+
const r = boxOf(anchor);
|
|
4269
|
+
host.style.top = `${r.bottom + 6}px`;
|
|
4270
|
+
if (align === 'start') { host.style.left = `${r.left}px`; host.style.right = ''; }
|
|
4271
|
+
else { host.style.right = `${Math.max(8, innerWidth - r.right)}px`; host.style.left = ''; }
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
// <nk-calendar name="due" value="2026-06-02" weeks weekend="6,0"></nk-calendar>
|
|
4275
|
+
// <nk-calendar range value="2026-06-08/2026-06-12"></nk-calendar>
|
|
4276
|
+
// <nk-calendar floating sheet id="picker"></nk-calendar> picker.show(button)
|
|
4277
|
+
// → [<div class="nk-pop floating sheet open">]<div class="nk-calendar weeks">
|
|
4278
|
+
// <div class="cal-head"><div class="cal-title">June 2026</div><button class="cal-nav">Today</button>‹ ›</div>
|
|
4279
|
+
// <div class="cal-grid"><span class="cal-wd">W</span>…<span class="cal-week">23</span><button class="cal-day selected">2</button>…</div>
|
|
4280
|
+
// [<div class="cal-foot"><input class="nk-input" type="time"></div>]</div>
|
|
4281
|
+
//
|
|
4282
|
+
// Notion's date picker (NotionKit 1.9.0), after GlassKit Elements'
|
|
4283
|
+
// glk-calendar, with what a planning tool needs on top: a range, ISO
|
|
4284
|
+
// calendar weeks, days not worked, marks and a time.
|
|
4285
|
+
// value: YYYY-MM-DD; with `range` the ISO interval "start/end"; with `time`
|
|
4286
|
+
// YYYY-MM-DDTHH:MM. Also as the properties value, start, end.
|
|
4287
|
+
// month (YYYY-MM shown; default the value's, else today's), min, max, today,
|
|
4288
|
+
// locale (default the page's lang), week-start (0 = Sunday … 6 = Saturday;
|
|
4289
|
+
// default from the locale, Monday where the browser cannot say), weeks,
|
|
4290
|
+
// weekend (weekdays not worked, "6,0" for Saturday and Sunday), range, time,
|
|
4291
|
+
// clearable, label and the texts today-label, prev-label, next-label,
|
|
4292
|
+
// week-label, time-label, clear-label. `time` belongs to single days; a
|
|
4293
|
+
// range has none.
|
|
4294
|
+
// days (property, or JSON attribute): { 'YYYY-MM-DD': { off, label, marks } }
|
|
4295
|
+
// – `off` greys a holiday, `label` names the day (tooltip and screen
|
|
4296
|
+
// reader), `marks` puts up to three dots in the nine colours on it.
|
|
4297
|
+
// Keys: arrows by a day or a week, Home/End to the ends of the week,
|
|
4298
|
+
// PageUp/PageDown by a month (Shift: a year); Enter or Space picks. Arrows
|
|
4299
|
+
// only move, so the picker stays quiet while someone looks around. Days
|
|
4300
|
+
// outside min/max are aria-disabled – in the arrow path and announced, never
|
|
4301
|
+
// picked. A range takes two picks, in either order. Form-associated: the
|
|
4302
|
+
// value goes with the form, reset restores it.
|
|
4303
|
+
// Events: nk-change { value, start, end, time } when a pick – for a range the
|
|
4304
|
+
// second one –, a new time or Clear changes the value; nk-month { month } when the month
|
|
4305
|
+
// changes; nk-toggle { open } with `floating`. `required` makes an empty
|
|
4306
|
+
// value invalid.
|
|
4307
|
+
// `floating` makes it a popover over the page – show(anchor) puts it under
|
|
4308
|
+
// the anchor, right edges aligned (align="start": left edges) – and `sheet`
|
|
4309
|
+
// a bottom sheet with 44px cells on a phone, as <nk-menu floating sheet>.
|
|
4310
|
+
// A pick closes it – the second of a range; with `time` Escape or a tap
|
|
4311
|
+
// outside does. Put a floating calendar directly under <body>.
|
|
4312
|
+
const STEPS = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };
|
|
4313
|
+
const floatSheet$1 = new CSSStyleSheet();
|
|
4314
|
+
floatSheet$1.replaceSync(`:host([floating]) { display: block; position: fixed; z-index: 60; pointer-events: none; }`);
|
|
4315
|
+
|
|
4316
|
+
class NkCalendar extends NkFormElement {
|
|
4317
|
+
static get hostStyles() { return floatSheet$1; }
|
|
4318
|
+
static get observedAttributes() {
|
|
4319
|
+
return ['value', 'month', 'min', 'max', 'today', 'locale', 'week-start', 'weeks', 'weekend', 'range', 'time', 'clearable', 'days',
|
|
4320
|
+
'label', 'today-label', 'prev-label', 'next-label', 'week-label', 'time-label', 'clear-label', 'floating', 'sheet', 'open', 'align', 'required'];
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4323
|
+
render() {
|
|
4324
|
+
// A value or month set as a property before the first connect wins over the attributes.
|
|
4325
|
+
this._readValue(this._pendingValue ?? this.getAttribute('value'));
|
|
4326
|
+
const month = this._pendingMonth || this._attrMonth();
|
|
4327
|
+
if (month) this._month = month;
|
|
4328
|
+
this._initialValue = this.getAttribute('value') ?? '';
|
|
4329
|
+
this._build();
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4332
|
+
// ── value ──
|
|
4333
|
+
_readValue(v) {
|
|
4334
|
+
const s = String(v ?? '');
|
|
4335
|
+
this._start = this._end = this._day = null;
|
|
4336
|
+
this._time = '';
|
|
4337
|
+
if (this.getBoolAttr('range')) {
|
|
4338
|
+
const [a, b] = s.split('/');
|
|
4339
|
+
this._start = parseDay(a) ? isoOf(parseDay(a)) : null;
|
|
4340
|
+
this._end = parseDay(b) ? isoOf(parseDay(b)) : null;
|
|
4341
|
+
} else if (parseDay(s)) {
|
|
4342
|
+
this._day = isoOf(parseDay(s));
|
|
4343
|
+
this._time = s.match(/T(\d{2}:\d{2})/)?.[1] ?? '';
|
|
4344
|
+
}
|
|
4345
|
+
// A new value brings its month; without one the month stays.
|
|
4346
|
+
const shown = this._day || this._start;
|
|
4347
|
+
this._month = shown ? shown.slice(0, 7) : (this._month || this._attrMonth() || this._todayIso().slice(0, 7));
|
|
4348
|
+
this._focus = null;
|
|
4349
|
+
}
|
|
4350
|
+
|
|
4351
|
+
_attrMonth() { const m = this.getAttribute('month'); return /^\d{4}-\d{2}$/.test(m || '') ? m : null; }
|
|
4352
|
+
_todayIso() { return this.getAttribute('today') || isoOf(new Date()); }
|
|
4353
|
+
|
|
4354
|
+
get value() {
|
|
4355
|
+
if (this.getBoolAttr('range')) return this._start ? `${this._start}${this._end ? `/${this._end}` : ''}` : '';
|
|
4356
|
+
return this._day ? `${this._day}${this.getBoolAttr('time') && this._time ? `T${this._time}` : ''}` : '';
|
|
4357
|
+
}
|
|
4358
|
+
set value(v) {
|
|
4359
|
+
this._readValue(v);
|
|
4360
|
+
if (this._grid) this._draw(); else this._pendingValue = String(v ?? '');
|
|
4361
|
+
}
|
|
4362
|
+
get start() { return this.getBoolAttr('range') ? this._start : this._day; }
|
|
4363
|
+
get end() { return this.getBoolAttr('range') ? this._end : this._day; }
|
|
4364
|
+
get month() { return this._month; }
|
|
4365
|
+
set month(v) {
|
|
4366
|
+
if (!/^\d{4}-\d{2}$/.test(v)) return;
|
|
4367
|
+
this._month = v; this._focus = null;
|
|
4368
|
+
if (this._grid) this._draw(); else this._pendingMonth = v;
|
|
4369
|
+
}
|
|
4370
|
+
get days() { return this._days ?? {}; }
|
|
4371
|
+
set days(v) { this._days = v && typeof v === 'object' ? v : {}; if (this._grid) this._draw(); }
|
|
4372
|
+
|
|
4373
|
+
// ── markup ──
|
|
4374
|
+
_build() {
|
|
4375
|
+
const floating = this.getBoolAttr('floating');
|
|
4376
|
+
this._cal = this.createElement('div', ['nk-calendar'], { role: 'group' });
|
|
4377
|
+
const head = this.createElement('div', ['cal-head']);
|
|
4378
|
+
this._title = this.createElement('div', ['cal-title'], { 'aria-live': 'polite' });
|
|
4379
|
+
this._todayBtn = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4380
|
+
this._prev = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4381
|
+
this._prev.innerHTML = CHEVRONS.prev;
|
|
4382
|
+
this._next = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4383
|
+
this._next.innerHTML = CHEVRONS.next;
|
|
4384
|
+
head.append(this._title, this._todayBtn, this._prev, this._next);
|
|
4385
|
+
this._grid = this.createElement('div', ['cal-grid']);
|
|
4386
|
+
this._foot = this.createElement('div', ['cal-foot']);
|
|
4387
|
+
this._timeInput = this.createElement('input', ['nk-input'], { type: 'time' });
|
|
4388
|
+
this._clear = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4389
|
+
this._cal.append(head, this._grid);
|
|
4390
|
+
this._pop = floating ? this.createElement('div', ['nk-pop', 'floating']) : null;
|
|
4391
|
+
if (this._pop) this._pop.appendChild(this._cal);
|
|
4392
|
+
this._wrapper.replaceChildren(this._pop ?? this._cal);
|
|
4393
|
+
this._draw();
|
|
4394
|
+
}
|
|
4395
|
+
|
|
4396
|
+
get _hasTime() { return this.getBoolAttr('time') && !this.getBoolAttr('range'); }
|
|
4397
|
+
get _locale() { return resolveLocale(this.getAttribute('locale')); }
|
|
4398
|
+
get _weekStart() {
|
|
4399
|
+
const n = Number(this.getAttribute('week-start'));
|
|
4400
|
+
return this.hasAttribute('week-start') && Number.isInteger(n) && n >= 0 && n <= 6 ? n : firstWeekday(this._locale);
|
|
4401
|
+
}
|
|
4402
|
+
|
|
4403
|
+
_syncPop() {
|
|
4404
|
+
this._pop?.classList.toggle('sheet', this.getBoolAttr('sheet'));
|
|
4405
|
+
this._pop?.classList.toggle('open', this.getBoolAttr('open'));
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
_draw() {
|
|
4409
|
+
const locale = this._locale, ws = this._weekStart, weeks = this.getBoolAttr('weeks'), range = this.getBoolAttr('range');
|
|
4410
|
+
const g = monthGrid(this._month, ws), today = this._todayIso();
|
|
4411
|
+
const min = this.getAttribute('min') || '', max = this.getAttribute('max') || '';
|
|
4412
|
+
const weekend = new Set((this.getAttribute('weekend') || '').split(',').map(s => s.trim()).filter(Boolean).map(Number));
|
|
4413
|
+
let days = this._days;
|
|
4414
|
+
if (!days && this.hasAttribute('days')) { try { days = JSON.parse(this.getAttribute('days')); } catch { days = {}; } }
|
|
4415
|
+
days ??= {};
|
|
4416
|
+
const long = new Intl.DateTimeFormat(locale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
|
|
4417
|
+
this._cal.classList.toggle('weeks', weeks);
|
|
4418
|
+
this._syncPop();
|
|
4419
|
+
const label = this.getAttribute('label');
|
|
4420
|
+
if (label) this._cal.setAttribute('aria-label', label); else this._cal.removeAttribute('aria-label');
|
|
4421
|
+
this._title.textContent = new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(g.first);
|
|
4422
|
+
this._todayBtn.textContent = this.getAttribute('today-label') || 'Today';
|
|
4423
|
+
this._prev.setAttribute('aria-label', this.getAttribute('prev-label') || 'Previous month');
|
|
4424
|
+
this._next.setAttribute('aria-label', this.getAttribute('next-label') || 'Next month');
|
|
4425
|
+
|
|
4426
|
+
// The one tab stop: the focused day, else the chosen one, else the 1st.
|
|
4427
|
+
const cells = Array.from({ length: 42 }, (_, i) => isoOf(g.day(i)));
|
|
4428
|
+
const chosen = range ? this._start : this._day;
|
|
4429
|
+
if (!this._focus || !cells.includes(this._focus)) this._focus = cells.includes(chosen) ? chosen : `${this._month}-01`;
|
|
4430
|
+
|
|
4431
|
+
const nodes = [];
|
|
4432
|
+
if (weeks) nodes.push(this._head(this.getAttribute('week-label') || weekLabel(locale)));
|
|
4433
|
+
for (const w of weekdayNames(locale, ws, 2)) nodes.push(this._head(w));
|
|
4434
|
+
for (let i = 0; i < 42; i++) {
|
|
4435
|
+
const d = g.day(i), iso = cells[i], info = days[iso] || {};
|
|
4436
|
+
if (weeks && i % 7 === 0) { const wk = this.createElement('span', ['cal-week'], { 'aria-hidden': 'true' }); wk.textContent = isoWeek(d); nodes.push(wk); }
|
|
4437
|
+
const inRange = range && this._start && this._end && iso > this._start && iso < this._end;
|
|
4438
|
+
const cls = ['cal-day', d.getMonth() !== g.m - 1 && 'out', (weekend.has(d.getDay()) || info.off) && 'off', iso === today && 'today',
|
|
4439
|
+
!range && iso === this._day && 'selected', range && iso === this._start && 'start', range && iso === (this._end || this._start) && this._start && 'end', inRange && 'in-range'].filter(Boolean);
|
|
4440
|
+
const day = this.createElement('button', cls, { type: 'button', 'data-date': iso, tabindex: iso === this._focus ? '0' : '-1',
|
|
4441
|
+
'aria-pressed': String(cls.includes('selected') || cls.includes('start') || cls.includes('end')),
|
|
4442
|
+
'aria-label': `${long.format(d)}${info.label ? `, ${info.label}` : ''}` });
|
|
4443
|
+
if (info.label) day.title = info.label;
|
|
4444
|
+
if ((min && iso < min) || (max && iso > max)) day.setAttribute('aria-disabled', 'true');
|
|
4445
|
+
day.textContent = d.getDate();
|
|
4446
|
+
const marks = (info.marks || []).slice(0, 3);
|
|
4447
|
+
if (marks.length) {
|
|
4448
|
+
const m = this.createElement('span', ['cal-marks']);
|
|
4449
|
+
for (const tone of marks) m.appendChild(this.createElement('i', [tone]));
|
|
4450
|
+
day.appendChild(m);
|
|
4451
|
+
}
|
|
4452
|
+
nodes.push(day);
|
|
4453
|
+
}
|
|
4454
|
+
// The days are drawn anew; focus inside the grid moves to the new tab stop.
|
|
4455
|
+
const focused = this._grid.contains(this._shadow.activeElement);
|
|
4456
|
+
this._grid.replaceChildren(...nodes);
|
|
4457
|
+
if (focused) this.focusDay();
|
|
4458
|
+
|
|
4459
|
+
const time = this._hasTime, clearable = this.getBoolAttr('clearable');
|
|
4460
|
+
this._timeInput.value = this._time;
|
|
4461
|
+
this._timeInput.setAttribute('aria-label', this.getAttribute('time-label') || 'Time');
|
|
4462
|
+
this._clear.textContent = this.getAttribute('clear-label') || 'Clear';
|
|
4463
|
+
this._foot.replaceChildren(...[time && this._timeInput, clearable && this._clear].filter(Boolean));
|
|
4464
|
+
if (time || clearable) this._cal.appendChild(this._foot); else this._foot.remove();
|
|
4465
|
+
this._syncForm();
|
|
4466
|
+
}
|
|
4467
|
+
|
|
4468
|
+
_syncForm() {
|
|
4469
|
+
this.setFormValue(this.value);
|
|
4470
|
+
if (this.getBoolAttr('required') && !this.value) this.setValidity({ valueMissing: true }, 'Please choose a date.', this._grid?.querySelector('[tabindex="0"]') ?? undefined);
|
|
4471
|
+
else this.setValidity({});
|
|
4472
|
+
}
|
|
4473
|
+
|
|
4474
|
+
_head(text) {
|
|
4475
|
+
const s = this.createElement('span', ['cal-wd'], { 'aria-hidden': 'true' });
|
|
4476
|
+
s.textContent = text;
|
|
4477
|
+
return s;
|
|
4478
|
+
}
|
|
4479
|
+
|
|
4480
|
+
// ── interaction ──
|
|
4481
|
+
_goMonth(month, focus) {
|
|
4482
|
+
if (month !== this._month) { this._month = month; this.emit('nk-month', { month }); }
|
|
4483
|
+
this._focus = focus ?? null;
|
|
4484
|
+
this._draw();
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
_pick(iso) {
|
|
4488
|
+
const day = this._grid.querySelector(`[data-date="${iso}"]`);
|
|
4489
|
+
if (day?.getAttribute('aria-disabled') === 'true') return;
|
|
4490
|
+
const before = this.value;
|
|
4491
|
+
let done = true;
|
|
4492
|
+
if (this.getBoolAttr('range')) {
|
|
4493
|
+
if (!this._start || this._end) { this._start = iso; this._end = null; done = false; }
|
|
4494
|
+
else if (iso < this._start) { this._end = this._start; this._start = iso; }
|
|
4495
|
+
else this._end = iso;
|
|
4496
|
+
} else this._day = iso;
|
|
4497
|
+
this._focus = iso;
|
|
4498
|
+
if (iso.slice(0, 7) !== this._month) this._goMonth(iso.slice(0, 7), iso); else this._draw();
|
|
4499
|
+
if (!done) return;
|
|
4500
|
+
// Only a new value is a change; the same day again just closes a popover.
|
|
4501
|
+
if (this.value !== before) this.emit('nk-change', { value: this.value, start: this.start, end: this.end, time: this._time || null });
|
|
4502
|
+
if (this.getBoolAttr('floating') && !this._hasTime) this.close();
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
setupEvents() {
|
|
4506
|
+
this._onGrid = (e) => { const day = e.target.closest('.cal-day'); if (day) this._pick(day.dataset.date); };
|
|
4507
|
+
this._onToday = () => { const t = this._todayIso(); this._goMonth(t.slice(0, 7), t); };
|
|
4508
|
+
this._onPrev = () => this._goMonth(stepMonth(this._month, -1));
|
|
4509
|
+
this._onNext = () => this._goMonth(stepMonth(this._month, 1));
|
|
4510
|
+
this._onKey = (e) => {
|
|
4511
|
+
// Enter and Space are the day button's own click.
|
|
4512
|
+
const day = e.target.closest?.('.cal-day');
|
|
4513
|
+
if (!day) return;
|
|
4514
|
+
const date = parseDay(day.dataset.date), ws = this._weekStart, wd = (date.getDay() - ws + 7) % 7;
|
|
4515
|
+
let target = null;
|
|
4516
|
+
if (STEPS[e.key]) target = addDays(date, STEPS[e.key]);
|
|
4517
|
+
else if (e.key === 'Home') target = addDays(date, -wd);
|
|
4518
|
+
else if (e.key === 'End') target = addDays(date, 6 - wd);
|
|
4519
|
+
else if (e.key === 'PageUp' || e.key === 'PageDown') {
|
|
4520
|
+
const months = (e.key === 'PageUp' ? -1 : 1) * (e.shiftKey ? 12 : 1);
|
|
4521
|
+
const last = new Date(date.getFullYear(), date.getMonth() + months + 1, 0).getDate();
|
|
4522
|
+
target = new Date(date.getFullYear(), date.getMonth() + months, Math.min(date.getDate(), last));
|
|
4523
|
+
}
|
|
4524
|
+
if (!target) return;
|
|
4525
|
+
e.preventDefault();
|
|
4526
|
+
const iso = isoOf(target);
|
|
4527
|
+
if (iso.slice(0, 7) !== this._month) this._goMonth(iso.slice(0, 7), iso);
|
|
4528
|
+
else { this._focus = iso; this._draw(); }
|
|
4529
|
+
};
|
|
4530
|
+
this._onTime = () => {
|
|
4531
|
+
this._time = this._timeInput.value;
|
|
4532
|
+
this._syncForm();
|
|
4533
|
+
if (this._day) this.emit('nk-change', { value: this.value, start: this.start, end: this.end, time: this._time || null });
|
|
4534
|
+
};
|
|
4535
|
+
this._onClear = () => {
|
|
4536
|
+
if (!this.value) return;
|
|
4537
|
+
this._day = this._start = this._end = null; this._time = '';
|
|
4538
|
+
this._draw();
|
|
4539
|
+
this.emit('nk-change', { value: '', start: null, end: null, time: null });
|
|
4540
|
+
};
|
|
4541
|
+
// Floating: a tap outside closes it and reaches nothing else; Escape closes (captured, before a modal around it).
|
|
4542
|
+
this._onOutside = (e) => {
|
|
4543
|
+
const path = e.composedPath();
|
|
4544
|
+
if (path.includes(this) || (this._anchor && path.includes(this._anchor))) return;
|
|
4545
|
+
e.preventDefault(); e.stopPropagation();
|
|
4546
|
+
this.close();
|
|
4547
|
+
};
|
|
4548
|
+
this._onEscape = (e) => { if (e.key === 'Escape' && this.getBoolAttr('floating') && this.getBoolAttr('open')) { e.stopPropagation(); this.close(); } };
|
|
4549
|
+
this._grid.addEventListener('click', this._onGrid);
|
|
4550
|
+
this._grid.addEventListener('keydown', this._onKey);
|
|
4551
|
+
this._todayBtn.addEventListener('click', this._onToday);
|
|
4552
|
+
this._prev.addEventListener('click', this._onPrev);
|
|
4553
|
+
this._next.addEventListener('click', this._onNext);
|
|
4554
|
+
this._timeInput.addEventListener('change', this._onTime);
|
|
4555
|
+
this._clear.addEventListener('click', this._onClear);
|
|
4556
|
+
document.addEventListener('keydown', this._onEscape, true);
|
|
4557
|
+
if (this.getBoolAttr('open')) document.addEventListener('click', this._onOutside, true);
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4560
|
+
teardownEvents() {
|
|
4561
|
+
this._grid?.removeEventListener('click', this._onGrid);
|
|
4562
|
+
this._grid?.removeEventListener('keydown', this._onKey);
|
|
4563
|
+
this._todayBtn?.removeEventListener('click', this._onToday);
|
|
4564
|
+
this._prev?.removeEventListener('click', this._onPrev);
|
|
4565
|
+
this._next?.removeEventListener('click', this._onNext);
|
|
4566
|
+
this._timeInput?.removeEventListener('change', this._onTime);
|
|
4567
|
+
this._clear?.removeEventListener('click', this._onClear);
|
|
4568
|
+
document.removeEventListener('keydown', this._onEscape, true);
|
|
4569
|
+
document.removeEventListener('click', this._onOutside, true);
|
|
4570
|
+
}
|
|
4571
|
+
|
|
4572
|
+
onAttributeChanged(name, _old, value) {
|
|
4573
|
+
if (name === 'value') { this._readValue(value); this._draw(); return; }
|
|
4574
|
+
if (name === 'month') { this.month = value; return; }
|
|
4575
|
+
if (name === 'open' || name === 'sheet') { this._syncPop(); if (name === 'open') this._syncOpen(); return; }
|
|
4576
|
+
if (name === 'align') return;
|
|
4577
|
+
if (name === 'floating') { this.teardownEvents(); this._build(); if (this.isConnected) this.setupEvents(); return; }
|
|
4578
|
+
if (name === 'range') this._readValue(this.getAttribute('value'));
|
|
4579
|
+
if (name === 'days') this._days = null;
|
|
4580
|
+
this._draw();
|
|
4581
|
+
}
|
|
4582
|
+
|
|
4583
|
+
_syncOpen() {
|
|
4584
|
+
const open = this.getBoolAttr('open');
|
|
4585
|
+
if (this._anchor) (this._anchor.shadowRoot?.querySelector('button, a[href]') ?? this._anchor).setAttribute('aria-expanded', String(open));
|
|
4586
|
+
if (open) {
|
|
4587
|
+
this._returnFocus = deepActiveElement();
|
|
4588
|
+
if (this._returnFocus?.matches(':focus-visible')) requestAnimationFrame(() => this.focusDay());
|
|
4589
|
+
document.addEventListener('click', this._onOutside, true);
|
|
4590
|
+
} else {
|
|
4591
|
+
document.removeEventListener('click', this._onOutside, true);
|
|
4592
|
+
const back = this._returnFocus;
|
|
4593
|
+
this._returnFocus = null;
|
|
4594
|
+
const active = deepActiveElement();
|
|
4595
|
+
if (back?.isConnected && active && this._shadow.contains(active)) back.focus({ preventScroll: true });
|
|
4596
|
+
}
|
|
4597
|
+
this.emit('nk-toggle', { open });
|
|
4598
|
+
}
|
|
4599
|
+
|
|
4600
|
+
// ── form ──
|
|
4601
|
+
resetValue() { this._readValue(this._initialValue); this._draw(); }
|
|
4602
|
+
restoreValue(state) { this._readValue(state); this._draw(); }
|
|
4603
|
+
onFormDisabled(disabled) { this._cal?.toggleAttribute('inert', disabled); }
|
|
4604
|
+
|
|
4605
|
+
// ── API ──
|
|
4606
|
+
/** Opens under `anchor` (with `floating`), on the month of the value. */
|
|
4607
|
+
show(anchor) {
|
|
4608
|
+
if (anchor) { this._anchor = anchor; placeUnder(this, anchor, this.getAttribute('align')); }
|
|
4609
|
+
const shown = this.start;
|
|
4610
|
+
if (shown && shown.slice(0, 7) !== this._month) { this._month = shown.slice(0, 7); this._focus = null; this._draw(); }
|
|
4611
|
+
this.setBoolAttr('open', true);
|
|
4612
|
+
}
|
|
4613
|
+
close() { this.setBoolAttr('open', false); }
|
|
4614
|
+
toggle(anchor) { this.getBoolAttr('open') ? this.close() : this.show(anchor); }
|
|
4615
|
+
get open() { return this.getBoolAttr('open'); }
|
|
4616
|
+
set open(v) { this.setBoolAttr('open', v); }
|
|
4617
|
+
/** Moves focus to the day with the tab stop. */
|
|
4618
|
+
focusDay() { this._grid?.querySelector('[tabindex="0"]')?.focus(); }
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
customElements.define('nk-calendar', NkCalendar);
|
|
4622
|
+
|
|
4623
|
+
// <nk-peek id="peek" label="Database Table-View">
|
|
4624
|
+
// <nk-btn slot="actions" variant="topbar" aria-label="Open as page"><svg …></svg></nk-btn>
|
|
4625
|
+
// <nk-page-title>🗃️ Database Table-View</nk-page-title>
|
|
4626
|
+
// <nk-props>…</nk-props>
|
|
4627
|
+
// <div class="nk-prose">…</div>
|
|
4628
|
+
// <nk-comments>…</nk-comments>
|
|
4629
|
+
// </nk-peek>
|
|
4630
|
+
// → <div class="nk-peek-backdrop open"><aside class="nk-peek" role="dialog">
|
|
4631
|
+
// <div class="pk-bar"><button class="nk-topbar-btn">»</button>…actions…</div>
|
|
4632
|
+
// <div class="pk-body">…</div></aside></div>
|
|
4633
|
+
//
|
|
4634
|
+
// Notion's side peek (NotionKit 1.8.0): a row beside the table, which stays
|
|
4635
|
+
// usable – no scrim, nothing inert. show() slides it in and moves focus to
|
|
4636
|
+
// it; », Escape and a click elsewhere on the page close it, and Escape and »
|
|
4637
|
+
// hand focus back. A click that calls show() again – on another row – only
|
|
4638
|
+
// swaps the content, and clicks inside other overlays (a menu opened from
|
|
4639
|
+
// the peek) leave it open. Below 860px it is a bottom sheet over a dimmed
|
|
4640
|
+
// page; there it is modal: the page is inert and scroll-locked, the dimmed
|
|
4641
|
+
// page takes the tap that closes it. Put it directly under <body>.
|
|
4642
|
+
const CLOSE_ICON = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 17 5-5-5-5M13 17l5-5-5-5"/></svg>';
|
|
4643
|
+
const OVERLAYS = new Set(['nk-menu', 'nk-pop', 'nk-modal', 'nk-sheet', 'nk-cmdk', 'nk-toast']);
|
|
4644
|
+
const OVERLAY_CLASSES = ['nk-pop', 'nk-modal-backdrop', 'nk-sheet-backdrop', 'nk-cmdk-backdrop'];
|
|
4645
|
+
const phone = () => matchMedia('(max-width: 860px)').matches;
|
|
4646
|
+
|
|
4647
|
+
class NkPeek extends NkElement {
|
|
4648
|
+
static get observedAttributes() { return ['open', 'label', 'close-label']; }
|
|
4649
|
+
|
|
4650
|
+
render() {
|
|
4651
|
+
this._backdrop = this.createElement('div', ['nk-peek-backdrop']);
|
|
4652
|
+
this._box = this.createElement('aside', ['nk-peek'], { role: 'dialog', tabindex: '-1' });
|
|
4653
|
+
const bar = this.createElement('div', ['pk-bar']);
|
|
4654
|
+
this._close = this.createElement('button', ['nk-topbar-btn'], { type: 'button' });
|
|
4655
|
+
this._close.innerHTML = CLOSE_ICON;
|
|
4656
|
+
bar.append(this._close, this.createElement('slot', [], { name: 'actions' }));
|
|
4657
|
+
const body = this.createElement('div', ['pk-body']);
|
|
4658
|
+
body.appendChild(document.createElement('slot'));
|
|
4659
|
+
this._box.append(bar, body);
|
|
4660
|
+
this._backdrop.appendChild(this._box);
|
|
4661
|
+
this._wrapper.appendChild(this._backdrop);
|
|
4662
|
+
this._syncLabels();
|
|
4663
|
+
this._syncOpen();
|
|
4664
|
+
}
|
|
4665
|
+
|
|
4666
|
+
_syncLabels() {
|
|
4667
|
+
const label = this.getAttribute('label');
|
|
4668
|
+
if (label) this._box.setAttribute('aria-label', label); else this._box.removeAttribute('aria-label');
|
|
4669
|
+
this._close.setAttribute('aria-label', this.getAttribute('close-label') || 'Close');
|
|
4670
|
+
}
|
|
4671
|
+
|
|
4672
|
+
_syncOpen() {
|
|
4673
|
+
const open = this.getBoolAttr('open');
|
|
4674
|
+
this._backdrop.classList.toggle('open', open);
|
|
4675
|
+
if (open === this._wasOpen) return;
|
|
4676
|
+
this._wasOpen = open;
|
|
4677
|
+
if (open) {
|
|
4678
|
+
this._returnFocus = deepActiveElement();
|
|
4679
|
+
if (phone()) {
|
|
4680
|
+
this._modal = true;
|
|
4681
|
+
this._box.setAttribute('aria-modal', 'true');
|
|
4682
|
+
lockScroll();
|
|
4683
|
+
this._undoInert = inertOutside(this);
|
|
4684
|
+
}
|
|
4685
|
+
requestAnimationFrame(() => this._box.focus({ preventScroll: true }));
|
|
4686
|
+
} else {
|
|
4687
|
+
if (this._modal) { this._modal = false; this._box.removeAttribute('aria-modal'); unlockScroll(); this._undoInert?.(); this._undoInert = null; }
|
|
4688
|
+
const active = deepActiveElement();
|
|
4689
|
+
const inside = active && (this.contains(active) || this._shadow.contains(active) || active === document.body);
|
|
4690
|
+
const back = this._returnFocus;
|
|
4691
|
+
this._returnFocus = null;
|
|
4692
|
+
if (inside && back?.isConnected && typeof back.focus === 'function') back.focus({ preventScroll: true });
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
|
|
4696
|
+
setupEvents() {
|
|
4697
|
+
this._onClose = () => this.close();
|
|
4698
|
+
this._onBackdrop = (e) => { if (e.target === this._backdrop) this.close(); };
|
|
4699
|
+
this._onKey = (e) => { if (e.key === 'Escape' && this.getBoolAttr('open')) this.close(); };
|
|
4700
|
+
// Bubble phase, after the page's own handlers: a click that showed the
|
|
4701
|
+
// peek again (another row) must not close it.
|
|
4702
|
+
this._onOutside = (e) => {
|
|
4703
|
+
if (!this.getBoolAttr('open') || this._shownAt >= e.timeStamp) return;
|
|
4704
|
+
const path = e.composedPath();
|
|
4705
|
+
if (path.includes(this)) return;
|
|
4706
|
+
if (path.some(n => n.nodeType === 1 && (OVERLAYS.has(n.localName) || OVERLAY_CLASSES.some(c => n.classList.contains(c))))) return;
|
|
4707
|
+
this.close();
|
|
4708
|
+
};
|
|
4709
|
+
this._close.addEventListener('click', this._onClose);
|
|
4710
|
+
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
4711
|
+
document.addEventListener('keydown', this._onKey);
|
|
4712
|
+
document.addEventListener('click', this._onOutside);
|
|
4713
|
+
}
|
|
4714
|
+
|
|
4715
|
+
teardownEvents() {
|
|
4716
|
+
this._close?.removeEventListener('click', this._onClose);
|
|
4717
|
+
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
4718
|
+
document.removeEventListener('keydown', this._onKey);
|
|
4719
|
+
document.removeEventListener('click', this._onOutside);
|
|
4720
|
+
if (this._modal) { this._modal = false; unlockScroll(); this._undoInert?.(); this._undoInert = null; }
|
|
4721
|
+
this._wasOpen = false;
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4724
|
+
onAttributeChanged(name) {
|
|
4725
|
+
if (name !== 'open') { this._syncLabels(); return; }
|
|
4726
|
+
this._syncOpen();
|
|
4727
|
+
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
4728
|
+
}
|
|
4729
|
+
|
|
4730
|
+
show() { this._shownAt = performance.now(); this.setBoolAttr('open', true); }
|
|
4731
|
+
close() { this.setBoolAttr('open', false); }
|
|
4732
|
+
toggle() { this.getBoolAttr('open') ? this.close() : this.show(); }
|
|
4733
|
+
|
|
4734
|
+
get open() { return this.getBoolAttr('open'); }
|
|
4735
|
+
set open(v) { v ? this.show() : this.close(); }
|
|
4736
|
+
}
|
|
4737
|
+
|
|
4738
|
+
customElements.define('nk-peek', NkPeek);
|
|
4739
|
+
|
|
3912
4740
|
// <nk-modal id="settings">
|
|
3913
4741
|
// <nk-settings-user slot="user" name="…" mail="…"></nk-settings-user>
|
|
3914
4742
|
// <nk-settings-pane name="profile" group="Account" icon="👤" label="My profile" title="My profile" active>…</nk-settings-pane>
|
|
@@ -4382,16 +5210,6 @@ customElements.define('nk-cmdk', NkCmdk);
|
|
|
4382
5210
|
const floatSheet = new CSSStyleSheet();
|
|
4383
5211
|
floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; z-index: 60; pointer-events: none; }`);
|
|
4384
5212
|
|
|
4385
|
-
/** The border box of an element, or of the first descendant with one (display: contents hosts). */
|
|
4386
|
-
function boxOf(el) {
|
|
4387
|
-
if (el.getClientRects().length) return el.getBoundingClientRect();
|
|
4388
|
-
for (const child of [...(el.shadowRoot?.children ?? []), ...el.children]) {
|
|
4389
|
-
const r = boxOf(child);
|
|
4390
|
-
if (r.width || r.height) return r;
|
|
4391
|
-
}
|
|
4392
|
-
return el.getBoundingClientRect();
|
|
4393
|
-
}
|
|
4394
|
-
|
|
4395
5213
|
class NkMenu extends NkElement {
|
|
4396
5214
|
static get hostStyles() { return floatSheet; }
|
|
4397
5215
|
static get observedAttributes() { return ['floating', 'sheet', 'open', 'align']; }
|
|
@@ -4432,10 +5250,7 @@ class NkMenu extends NkElement {
|
|
|
4432
5250
|
show(anchor) {
|
|
4433
5251
|
if (anchor) {
|
|
4434
5252
|
this._anchor = anchor;
|
|
4435
|
-
|
|
4436
|
-
this.style.top = `${r.bottom + 6}px`;
|
|
4437
|
-
if (this.getAttribute('align') === 'start') { this.style.left = `${r.left}px`; this.style.right = ''; }
|
|
4438
|
-
else { this.style.right = `${Math.max(8, innerWidth - r.right)}px`; this.style.left = ''; }
|
|
5253
|
+
placeUnder(this, anchor, this.getAttribute('align'));
|
|
4439
5254
|
}
|
|
4440
5255
|
this.setBoolAttr('open', true);
|
|
4441
5256
|
}
|
|
@@ -5043,8 +5858,10 @@ function compareBy(column, dir = 1) {
|
|
|
5043
5858
|
// `wrap` lets cell text break (`.nk-table.wrap`), like Notion's "wrap column".
|
|
5044
5859
|
// Standalone: view.columns = […]; view.rows = […]; Inside <nk-database> the
|
|
5045
5860
|
// database pushes `data`. → <div class="nk-table-wrap"><table class="nk-table">…</table><div class="nk-new-row">+ New page</div></div>
|
|
5046
|
-
// Cells are plain markup from renderPropertyCell(); rows fire nk-select
|
|
5047
|
-
//
|
|
5861
|
+
// Cells are plain markup from renderPropertyCell(); rows fire nk-select
|
|
5862
|
+
// { row, id, key, cell } – `key` and `cell` say which cell was hit, to open
|
|
5863
|
+
// an editor there, like the date picker under a due date – checkboxes
|
|
5864
|
+
// nk-change, headers nk-action { action: 'sort' } (and sort locally
|
|
5048
5865
|
// with `sortable`), the add row nk-action { action: 'new-row' }.
|
|
5049
5866
|
class NkTableView extends NkElement {
|
|
5050
5867
|
static get observedAttributes() { return ['name', 'label', 'badge', 'count', 'new-row', 'new-row-label', 'sortable', 'sort-key', 'sort-dir', 'wrap']; }
|
|
@@ -5112,7 +5929,11 @@ class NkTableView extends NkElement {
|
|
|
5112
5929
|
}
|
|
5113
5930
|
if (e.target.closest('input[type=checkbox], a')) return;
|
|
5114
5931
|
const tr = e.target.closest('tr[data-id]');
|
|
5115
|
-
if (tr)
|
|
5932
|
+
if (!tr) return;
|
|
5933
|
+
// Which cell: `key` names its column, `cell` is there to anchor an editor to.
|
|
5934
|
+
const cell = e.target.closest('td');
|
|
5935
|
+
const row = this._rowById(tr.dataset.id);
|
|
5936
|
+
this.emit('nk-select', { row, id: row?.id, value: row?.id, key: cell ? this._columns[cell.cellIndex]?.key : undefined, cell });
|
|
5116
5937
|
};
|
|
5117
5938
|
this._onChange = (e) => {
|
|
5118
5939
|
const input = e.target;
|
|
@@ -5363,6 +6184,139 @@ class NkListView extends NkElement {
|
|
|
5363
6184
|
|
|
5364
6185
|
customElements.define('nk-list-view', NkListView);
|
|
5365
6186
|
|
|
6187
|
+
// <nk-calendar-view name="calendar" label="📅 Calendar" date-key="due" weeks></nk-calendar-view>
|
|
6188
|
+
// The fourth database view (NotionKit 1.9.0): a month, the rows as cards on
|
|
6189
|
+
// their dates. `date-key` names the date column (default: the first one),
|
|
6190
|
+
// `title-key` the title (default: the title column); dates are YYYY-MM-DD or
|
|
6191
|
+
// D.M.YYYY, a range { start, end } stands on its start. month (YYYY-MM;
|
|
6192
|
+
// default today's), weeks (the ISO week in front of each row), week-start
|
|
6193
|
+
// (0 = Sunday … 6 = Saturday; default from the locale), weekend (weekdays
|
|
6194
|
+
// washed like the days of other months, "6,0"), today, locale and the texts
|
|
6195
|
+
// today-label, prev-label, next-label, week-label.
|
|
6196
|
+
// Standalone: view.columns = […]; view.rows = […]. Inside <nk-database> the
|
|
6197
|
+
// database pushes the data. A card fires nk-select { row, id, value } like a
|
|
6198
|
+
// row of the table, Today and ‹ › nk-month { month }.
|
|
6199
|
+
// → <div class="nk-calendar-view weeks"><div class="cv-head"><div class="cv-title">May 2026</div><button class="cal-nav">Today</button>‹ ›</div>
|
|
6200
|
+
// <div class="cv-grid"><div class="cv-wd">W</div>…<div class="cv-week">21</div><div class="cv-day today"><span class="cv-num">20</span><button class="cv-item">🗃️ …</button></div>…</div></div>
|
|
6201
|
+
class NkCalendarView extends NkElement {
|
|
6202
|
+
static get observedAttributes() {
|
|
6203
|
+
return ['name', 'label', 'badge', 'count', 'date-key', 'title-key', 'month', 'weeks', 'week-start', 'weekend', 'today', 'locale',
|
|
6204
|
+
'today-label', 'prev-label', 'next-label', 'week-label'];
|
|
6205
|
+
}
|
|
6206
|
+
|
|
6207
|
+
render() {
|
|
6208
|
+
this._box = this.createElement('div', ['nk-calendar-view']);
|
|
6209
|
+
const head = this.createElement('div', ['cv-head']);
|
|
6210
|
+
this._title = this.createElement('div', ['cv-title']);
|
|
6211
|
+
this._todayBtn = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6212
|
+
this._prev = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6213
|
+
this._prev.innerHTML = CHEVRONS.prev;
|
|
6214
|
+
this._next = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6215
|
+
this._next.innerHTML = CHEVRONS.next;
|
|
6216
|
+
head.append(this._title, this._todayBtn, this._prev, this._next);
|
|
6217
|
+
this._grid = this.createElement('div', ['cv-grid']);
|
|
6218
|
+
this._box.append(head, this._grid);
|
|
6219
|
+
this._wrapper.appendChild(this._box);
|
|
6220
|
+
this._columns ??= []; this._rows ??= [];
|
|
6221
|
+
this._month ??= this._attrMonth() ?? this._todayIso().slice(0, 7);
|
|
6222
|
+
this._render();
|
|
6223
|
+
this.closest('nk-database')?.requestSync?.();
|
|
6224
|
+
}
|
|
6225
|
+
|
|
6226
|
+
_attrMonth() { const m = this.getAttribute('month'); return /^\d{4}-\d{2}$/.test(m || '') ? m : null; }
|
|
6227
|
+
_todayIso() { return this.getAttribute('today') || isoOf(new Date()); }
|
|
6228
|
+
_dateColumn() {
|
|
6229
|
+
const key = this.getAttribute('date-key');
|
|
6230
|
+
return this._columns.find(c => c.key === key) || this._columns.find(c => c.type === 'date') || null;
|
|
6231
|
+
}
|
|
6232
|
+
_titleColumn() {
|
|
6233
|
+
const key = this.getAttribute('title-key');
|
|
6234
|
+
return this._columns.find(c => c.key === key) || this._columns.find(c => c.title) || this._columns[0] || null;
|
|
6235
|
+
}
|
|
6236
|
+
|
|
6237
|
+
_render() {
|
|
6238
|
+
if (!this._grid) return;
|
|
6239
|
+
const locale = resolveLocale(this.getAttribute('locale')), weeks = this.getBoolAttr('weeks');
|
|
6240
|
+
const n = Number(this.getAttribute('week-start'));
|
|
6241
|
+
const ws = this.hasAttribute('week-start') && Number.isInteger(n) && n >= 0 && n <= 6 ? n : firstWeekday(locale);
|
|
6242
|
+
const g = monthGrid(this._month, ws), today = this._todayIso();
|
|
6243
|
+
const weekend = new Set((this.getAttribute('weekend') || '').split(',').map(s => s.trim()).filter(Boolean).map(Number));
|
|
6244
|
+
const dateCol = this._dateColumn(), titleCol = this._titleColumn(), byDay = {};
|
|
6245
|
+
if (dateCol) for (const row of this._rows) {
|
|
6246
|
+
const d = parseDay(row[dateCol.key]);
|
|
6247
|
+
if (d) (byDay[isoOf(d)] ||= []).push(row);
|
|
6248
|
+
}
|
|
6249
|
+
this._box.classList.toggle('weeks', weeks);
|
|
6250
|
+
this._title.textContent = new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(g.first);
|
|
6251
|
+
this._todayBtn.textContent = this.getAttribute('today-label') || 'Today';
|
|
6252
|
+
this._prev.setAttribute('aria-label', this.getAttribute('prev-label') || 'Previous month');
|
|
6253
|
+
this._next.setAttribute('aria-label', this.getAttribute('next-label') || 'Next month');
|
|
6254
|
+
|
|
6255
|
+
const cell = (cls, text) => { const el = this.createElement('div', [cls]); el.textContent = text; return el; };
|
|
6256
|
+
const nodes = [];
|
|
6257
|
+
if (weeks) nodes.push(cell('cv-wd', this.getAttribute('week-label') || weekLabel(locale)));
|
|
6258
|
+
for (const w of weekdayNames(locale, ws)) nodes.push(cell('cv-wd', w));
|
|
6259
|
+
for (let i = 0; i < g.rows * 7; i++) {
|
|
6260
|
+
const d = g.day(i), iso = isoOf(d);
|
|
6261
|
+
if (weeks && i % 7 === 0) nodes.push(cell('cv-week', isoWeek(d)));
|
|
6262
|
+
const day = this.createElement('div', ['cv-day', d.getMonth() !== g.m - 1 && 'out', weekend.has(d.getDay()) && 'off', iso === today && 'today'].filter(Boolean));
|
|
6263
|
+
const num = this.createElement('span', ['cv-num']);
|
|
6264
|
+
num.textContent = d.getDate();
|
|
6265
|
+
day.appendChild(num);
|
|
6266
|
+
for (const row of byDay[iso] || []) {
|
|
6267
|
+
const item = this.createElement('button', ['cv-item'], { type: 'button', 'data-id': row.id ?? '' });
|
|
6268
|
+
const title = titleCol ? String(row[titleCol.key] ?? '') : '';
|
|
6269
|
+
item.textContent = row.icon ? `${row.icon} ${title}` : title;
|
|
6270
|
+
day.appendChild(item);
|
|
6271
|
+
}
|
|
6272
|
+
nodes.push(day);
|
|
6273
|
+
}
|
|
6274
|
+
this._grid.replaceChildren(...nodes);
|
|
6275
|
+
}
|
|
6276
|
+
|
|
6277
|
+
_goMonth(month) {
|
|
6278
|
+
if (month === this._month) return;
|
|
6279
|
+
this._month = month;
|
|
6280
|
+
this._render();
|
|
6281
|
+
this.emit('nk-month', { month });
|
|
6282
|
+
}
|
|
6283
|
+
|
|
6284
|
+
setupEvents() {
|
|
6285
|
+
this._onClick = (e) => {
|
|
6286
|
+
if (e.target.closest('.cal-nav') === this._todayBtn) { this._goMonth(this._todayIso().slice(0, 7)); return; }
|
|
6287
|
+
if (e.target.closest('.cal-nav') === this._prev) { this._goMonth(stepMonth(this._month, -1)); return; }
|
|
6288
|
+
if (e.target.closest('.cal-nav') === this._next) { this._goMonth(stepMonth(this._month, 1)); return; }
|
|
6289
|
+
const item = e.target.closest('.cv-item');
|
|
6290
|
+
if (item) { const row = this._rowById(item.dataset.id); this.emit('nk-select', { row, id: row?.id, value: row?.id }); }
|
|
6291
|
+
};
|
|
6292
|
+
this._box.addEventListener('click', this._onClick);
|
|
6293
|
+
}
|
|
6294
|
+
|
|
6295
|
+
teardownEvents() { this._box?.removeEventListener('click', this._onClick); }
|
|
6296
|
+
|
|
6297
|
+
_rowById(id) { return this._rows.find(r => String(r.id) === String(id)); }
|
|
6298
|
+
|
|
6299
|
+
onAttributeChanged(name) {
|
|
6300
|
+
if (name === 'month') this._month = this._attrMonth() ?? this._month;
|
|
6301
|
+
this._render();
|
|
6302
|
+
if (name === 'label' || name === 'badge' || name === 'count') this.closest('nk-database')?.requestSync?.();
|
|
6303
|
+
}
|
|
6304
|
+
|
|
6305
|
+
get name() { return this.getAttribute('name') || 'calendar'; }
|
|
6306
|
+
/** The month shown, YYYY-MM. */
|
|
6307
|
+
get month() { return this._month; }
|
|
6308
|
+
set month(v) { if (!/^\d{4}-\d{2}$/.test(v)) return; if (this._grid) this._goMonth(v); else this._month = v; }
|
|
6309
|
+
get columns() { return this._columns; }
|
|
6310
|
+
set columns(v) { this._columns = Array.isArray(v) ? v : []; this._render(); }
|
|
6311
|
+
get rows() { return this._rows; }
|
|
6312
|
+
set rows(v) { this._rows = Array.isArray(v) ? v : []; this._render(); }
|
|
6313
|
+
set data({ columns, rows }) { this.setData(columns, rows); }
|
|
6314
|
+
setData(columns, rows) { this._columns = columns || []; this._rows = rows || []; this._render(); }
|
|
6315
|
+
refresh() { this._render(); }
|
|
6316
|
+
}
|
|
6317
|
+
|
|
6318
|
+
customElements.define('nk-calendar-view', NkCalendarView);
|
|
6319
|
+
|
|
5366
6320
|
// <nk-filter-bar add no-filter no-sort></nk-filter-bar>
|
|
5367
6321
|
// bar.filters = [{ key: 'status', value: 'done', op: 'is-not', label: 'Status: Open' }];
|
|
5368
6322
|
// The filters in effect as NotionKit's filter pills (1.7.0), no inline style:
|
|
@@ -5687,4 +6641,4 @@ class NkAiInputRow extends NkElement {
|
|
|
5687
6641
|
|
|
5688
6642
|
customElements.define('nk-ai-input-row', NkAiInputRow);
|
|
5689
6643
|
|
|
5690
|
-
export { NkAiInputRow, NkAiMsg, NkAiThread, NkApp, NkAvatar, NkAvatarGroup, NkBanner, NkBlockHost, NkBoardView, NkBreadcrumb, NkBtn, NkCallout, NkCheck, NkCmdk, NkCode, NkComment, NkComments, NkDangerZone, NkDatabase, NkDivider, NkElement, NkEmojiPicker, NkEmpty, NkField, NkFields, NkFilterBar, NkFormElement, NkHeading, NkInput, NkKbd, NkListView, NkMemberList, NkMemberRow, NkMention, NkMenu, NkMenuItem, NkModal, NkModelCard, NkPage, NkPageActions, NkPageCover, NkPageTitle, NkPanel, NkPanels, NkPop, NkProfileRow, NkProgress, NkProp, NkProps, NkQuote, NkRadio, NkSectionLabel, NkSegmented, NkSelect, NkSettingsPane, NkSettingsUser, NkSheet, NkSidebar, NkSkeleton, NkSlider, NkStat, NkStats, NkSteps, NkSwitch, NkSynced, NkTab, NkTabBar, NkTabBarItem, NkTableView, NkTabs, NkTag, NkTemplateBtn, NkTextarea, NkThemeToggle, NkToast, NkTodo, NkToggle, NkTopbar, NkTree, NkTreeItem, NkWorkspaceSwitcher, compareBy, componentsSheet, renderPropertyCell, tagFor };
|
|
6644
|
+
export { NkAiInputRow, NkAiMsg, NkAiThread, NkApp, NkAvatar, NkAvatarGroup, NkBanner, NkBlockHost, NkBoardView, NkBookmark, NkBreadcrumb, NkBtn, NkCalendar, NkCalendarView, NkCallout, NkCheck, NkCmdk, NkCode, NkComment, NkComments, NkCopyField, NkDangerZone, NkDatabase, NkDivider, NkElement, NkEmojiPicker, NkEmpty, NkField, NkFields, NkFilterBar, NkFormElement, NkHeading, NkImagePicker, NkInput, NkKbd, NkListView, NkMemberList, NkMemberRow, NkMention, NkMenu, NkMenuItem, NkModal, NkModelCard, NkPage, NkPageActions, NkPageCover, NkPageTitle, NkPanel, NkPanels, NkPeek, NkPop, NkProfileRow, NkProgress, NkProp, NkProps, NkQuote, NkRadio, NkSectionLabel, NkSegmented, NkSelect, NkSettingsPane, NkSettingsUser, NkSheet, NkSidebar, NkSkeleton, NkSlider, NkStat, NkStats, NkSteps, NkSwitch, NkSynced, NkTab, NkTabBar, NkTabBarItem, NkTableView, NkTabs, NkTag, NkTemplateBtn, NkTextarea, NkThemeToggle, NkToast, NkTodo, NkToggle, NkTopbar, NkTree, NkTreeItem, NkWorkspaceSwitcher, compareBy, componentsSheet, renderPropertyCell, tagFor };
|