@jungherz-de/notionkit-elements 1.8.0 → 1.10.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 +13 -13
- package/dist/components/nk-app.js +8 -1
- package/dist/components/nk-btn.js +17 -3
- package/dist/components/nk-calendar-view.js +138 -0
- package/dist/components/nk-calendar.js +356 -0
- package/dist/components/nk-dialog.js +150 -0
- package/dist/components/nk-menu.js +2 -14
- package/dist/components/nk-peek.js +80 -5
- package/dist/components/nk-sidebar.js +68 -6
- package/dist/components/nk-table-view.js +9 -3
- package/dist/components/nk-tooltip.js +138 -0
- package/dist/components/nk-workspace-switcher.js +1 -1
- package/dist/components/shared/dates-a32DcW1l.js +67 -0
- package/dist/components/shared/floating-CxHxy-Cb.js +37 -0
- package/dist/notionkit-elements.esm.js +1102 -91
- package/dist/notionkit-elements.js +1105 -90
- package/dist/notionkit-elements.min.js +1 -1
- package/package.json +3 -3
- 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-btn.js +17 -3
- package/src/components/forms/nk-calendar.js +354 -0
- package/src/components/overlays/nk-dialog.js +148 -0
- package/src/components/overlays/nk-menu.js +2 -14
- package/src/components/overlays/nk-peek.js +80 -5
- package/src/components/overlays/nk-tooltip.js +136 -0
- package/src/components/shell/nk-app.js +8 -1
- package/src/components/shell/nk-sidebar.js +68 -6
- package/src/components/shell/nk-workspace-switcher.js +1 -1
- package/src/index.js +4 -0
- package/src/util/dates.js +65 -0
- package/src/util/floating.js +35 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// NotionKit v1.
|
|
1
|
+
// NotionKit v1.10.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-* …
|
|
5
|
-
const tokensCss = ":root{color-scheme:light;--nk-bg: #ffffff;--nk-bg-sidebar: #f9f8f7;--nk-bg-hover: rgba(55,53,47,.06);--nk-bg-active: rgba(55,53,47,.08);--nk-bg-callout: #f0efed;--nk-bg-code: #f7f6f3;--nk-bg-card: #ffffff;--nk-bg-input: rgba(242,241,238,.6);--nk-text: #2c2c2b;--nk-text-secondary: #7d7a75;--nk-text-tertiary: #91918e;--nk-text-sidebar: #5f5e5b;--nk-border: rgba(28,19,1,.11);--nk-border-strong: rgba(27,21,0,.19);--nk-accent: #2383e2;--nk-on-accent: #ffffff;--nk-danger: #cd3c3a;--nk-tag-gray-bg: #e3e2e0;--nk-tag-gray-text: #32302c;--nk-tag-brown-bg: #eee0da;--nk-tag-brown-text: #442a1e;--nk-tag-orange-bg: #fadec9;--nk-tag-orange-text: #49290e;--nk-tag-yellow-bg: #fdecc8;--nk-tag-yellow-text: #402c1b;--nk-tag-green-bg: #dbeddb;--nk-tag-green-text: #1c3829;--nk-tag-blue-bg: #d3e5ef;--nk-tag-blue-text: #183347;--nk-tag-purple-bg: #e8deee;--nk-tag-purple-text: #412454;--nk-tag-pink-bg: #f5e0e9;--nk-tag-pink-text: #4c2337;--nk-tag-red-bg: #ffe2dd;--nk-tag-red-text: #5d1715;--nk-tint-gray: #f1f1ef;--nk-color-gray: #787774;--nk-tint-brown: #f4eeee;--nk-color-brown: #9f6b53;--nk-tint-orange: #fbecdd;--nk-color-orange: #d9730d;--nk-tint-yellow: #fbf3db;--nk-color-yellow: #cb912f;--nk-tint-green: #edf3ec;--nk-color-green: #448361;--nk-tint-blue: #e7f3f8;--nk-color-blue: #337ea9;--nk-tint-purple: #f8f3fc;--nk-color-purple: #9065b0;--nk-tint-pink: #fcf1f6;--nk-color-pink: #c14c8a;--nk-tint-red: #fdebec;--nk-color-red: #cd3c3a;--nk-decor-purple: #9065b0;--nk-decor-blue: #529cca;--nk-decor-orange: #d9730d;--nk-scrim: rgba(15,15,15,.6);--nk-scrim-soft: rgba(15,15,15,.5);--nk-sidebar-width: 260px;--nk-tab-bar-height: 58px;--nk-radius: 6px;--nk-font: ui-sans-serif, -apple-system, \"Segoe UI\", Inter, Helvetica, Arial, sans-serif;--nk-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--nk-shadow-menu: rgba(15,15,15,.05) 0px 0px 0px 1px, rgba(15,15,15,.1) 0px 3px 6px, rgba(15,15,15,.2) 0px 9px 24px;--nk-shadow-card: 0 1px 2px rgba(0,0,0,.04);--nk-shadow-btn: inset 0 0 0 1px rgba(15,15,15,.1), 0 1px 2px rgba(15,15,15,.1);--nk-shadow-knob: 0 1px 2px rgba(0,0,0,.2);--nk-shadow-segment: 0 1px 2px rgba(0,0,0,.08)}[data-theme=dark]{color-scheme:dark;--nk-bg: #191919;--nk-bg-sidebar: #202020;--nk-bg-hover: rgba(255,255,255,.055);--nk-bg-active: rgba(255,255,255,.08);--nk-bg-callout: #252525;--nk-bg-code: #202020;--nk-bg-card: #202020;--nk-bg-input: rgba(255,255,255,.055);--nk-text: rgba(255,255,255,.81);--nk-text-secondary: rgba(255,255,255,.46);--nk-text-tertiary: rgba(255,255,255,.32);--nk-text-sidebar: rgba(255,255,255,.62);--nk-border: rgba(255,255,255,.094);--nk-border-strong: rgba(255,255,255,.16);--nk-accent: #529CCA;--nk-danger: #df5452;--nk-tag-gray-bg: #373737;--nk-tag-gray-text: rgba(255,255,255,.85);--nk-tag-brown-bg: #603b2c;--nk-tag-brown-text: rgba(255,255,255,.85);--nk-tag-orange-bg: #854c1d;--nk-tag-orange-text: rgba(255,255,255,.85);--nk-tag-yellow-bg: #89632a;--nk-tag-yellow-text: rgba(255,255,255,.85);--nk-tag-green-bg: #2b593f;--nk-tag-green-text: rgba(255,255,255,.85);--nk-tag-blue-bg: #28456c;--nk-tag-blue-text: rgba(255,255,255,.85);--nk-tag-purple-bg: #492f64;--nk-tag-purple-text: rgba(255,255,255,.85);--nk-tag-pink-bg: #69314c;--nk-tag-pink-text: rgba(255,255,255,.85);--nk-tag-red-bg: #6e3630;--nk-tag-red-text: rgba(255,255,255,.85);--nk-tint-gray: #252525;--nk-color-gray: #9b9b9b;--nk-tint-brown: #2e2724;--nk-color-brown: #ba856f;--nk-tint-orange: #36291f;--nk-color-orange: #c77d48;--nk-tint-yellow: #372e20;--nk-color-yellow: #ca8f3d;--nk-tint-green: #242b26;--nk-color-green: #529e72;--nk-tint-blue: #1f282d;--nk-color-blue: #5e87c9;--nk-tint-purple: #2a2430;--nk-color-purple: #9d68d3;--nk-tint-pink: #2e2328;--nk-color-pink: #d15796;--nk-tint-red: #332523;--nk-color-red: #df5452;--nk-shadow-menu: rgba(15,15,15,.2) 0px 0px 0px 1px, rgba(15,15,15,.4) 0px 3px 6px, rgba(15,15,15,.6) 0px 9px 24px;--nk-shadow-card: none;--nk-shadow-btn: inset 0 0 0 1px rgba(255,255,255,.1), 0 1px 2px rgba(0,0,0,.3)}";
|
|
5
|
+
const tokensCss = ":root{color-scheme:light;--nk-bg: #ffffff;--nk-bg-sidebar: #f9f8f7;--nk-bg-hover: rgba(55,53,47,.06);--nk-bg-active: rgba(55,53,47,.08);--nk-bg-callout: #f0efed;--nk-bg-code: #f7f6f3;--nk-bg-card: #ffffff;--nk-bg-input: rgba(242,241,238,.6);--nk-text: #2c2c2b;--nk-text-secondary: #7d7a75;--nk-text-tertiary: #91918e;--nk-text-sidebar: #5f5e5b;--nk-border: rgba(28,19,1,.11);--nk-border-strong: rgba(27,21,0,.19);--nk-accent: #2383e2;--nk-on-accent: #ffffff;--nk-danger: #cd3c3a;--nk-tag-gray-bg: #e3e2e0;--nk-tag-gray-text: #32302c;--nk-tag-brown-bg: #eee0da;--nk-tag-brown-text: #442a1e;--nk-tag-orange-bg: #fadec9;--nk-tag-orange-text: #49290e;--nk-tag-yellow-bg: #fdecc8;--nk-tag-yellow-text: #402c1b;--nk-tag-green-bg: #dbeddb;--nk-tag-green-text: #1c3829;--nk-tag-blue-bg: #d3e5ef;--nk-tag-blue-text: #183347;--nk-tag-purple-bg: #e8deee;--nk-tag-purple-text: #412454;--nk-tag-pink-bg: #f5e0e9;--nk-tag-pink-text: #4c2337;--nk-tag-red-bg: #ffe2dd;--nk-tag-red-text: #5d1715;--nk-tint-gray: #f1f1ef;--nk-color-gray: #787774;--nk-tint-brown: #f4eeee;--nk-color-brown: #9f6b53;--nk-tint-orange: #fbecdd;--nk-color-orange: #d9730d;--nk-tint-yellow: #fbf3db;--nk-color-yellow: #cb912f;--nk-tint-green: #edf3ec;--nk-color-green: #448361;--nk-tint-blue: #e7f3f8;--nk-color-blue: #337ea9;--nk-tint-purple: #f8f3fc;--nk-color-purple: #9065b0;--nk-tint-pink: #fcf1f6;--nk-color-pink: #c14c8a;--nk-tint-red: #fdebec;--nk-color-red: #cd3c3a;--nk-decor-purple: #9065b0;--nk-decor-blue: #529cca;--nk-decor-orange: #d9730d;--nk-scrim: rgba(15,15,15,.6);--nk-scrim-soft: rgba(15,15,15,.5);--nk-sidebar-width: 260px;--nk-peek-width: 560px;--nk-tab-bar-height: 58px;--nk-radius: 6px;--nk-font: ui-sans-serif, -apple-system, \"Segoe UI\", Inter, Helvetica, Arial, sans-serif;--nk-font-mono: ui-monospace, \"SF Mono\", Menlo, Consolas, monospace;--nk-shadow-menu: rgba(15,15,15,.05) 0px 0px 0px 1px, rgba(15,15,15,.1) 0px 3px 6px, rgba(15,15,15,.2) 0px 9px 24px;--nk-shadow-card: 0 1px 2px rgba(0,0,0,.04);--nk-shadow-btn: inset 0 0 0 1px rgba(15,15,15,.1), 0 1px 2px rgba(15,15,15,.1);--nk-shadow-knob: 0 1px 2px rgba(0,0,0,.2);--nk-shadow-segment: 0 1px 2px rgba(0,0,0,.08)}[data-theme=dark]{color-scheme:dark;--nk-bg: #191919;--nk-bg-sidebar: #202020;--nk-bg-hover: rgba(255,255,255,.055);--nk-bg-active: rgba(255,255,255,.08);--nk-bg-callout: #252525;--nk-bg-code: #202020;--nk-bg-card: #202020;--nk-bg-input: rgba(255,255,255,.055);--nk-text: rgba(255,255,255,.81);--nk-text-secondary: rgba(255,255,255,.46);--nk-text-tertiary: rgba(255,255,255,.32);--nk-text-sidebar: rgba(255,255,255,.62);--nk-border: rgba(255,255,255,.094);--nk-border-strong: rgba(255,255,255,.16);--nk-accent: #529CCA;--nk-danger: #df5452;--nk-tag-gray-bg: #373737;--nk-tag-gray-text: rgba(255,255,255,.85);--nk-tag-brown-bg: #603b2c;--nk-tag-brown-text: rgba(255,255,255,.85);--nk-tag-orange-bg: #854c1d;--nk-tag-orange-text: rgba(255,255,255,.85);--nk-tag-yellow-bg: #89632a;--nk-tag-yellow-text: rgba(255,255,255,.85);--nk-tag-green-bg: #2b593f;--nk-tag-green-text: rgba(255,255,255,.85);--nk-tag-blue-bg: #28456c;--nk-tag-blue-text: rgba(255,255,255,.85);--nk-tag-purple-bg: #492f64;--nk-tag-purple-text: rgba(255,255,255,.85);--nk-tag-pink-bg: #69314c;--nk-tag-pink-text: rgba(255,255,255,.85);--nk-tag-red-bg: #6e3630;--nk-tag-red-text: rgba(255,255,255,.85);--nk-tint-gray: #252525;--nk-color-gray: #9b9b9b;--nk-tint-brown: #2e2724;--nk-color-brown: #ba856f;--nk-tint-orange: #36291f;--nk-color-orange: #c77d48;--nk-tint-yellow: #372e20;--nk-color-yellow: #ca8f3d;--nk-tint-green: #242b26;--nk-color-green: #529e72;--nk-tint-blue: #1f282d;--nk-color-blue: #5e87c9;--nk-tint-purple: #2a2430;--nk-color-purple: #9d68d3;--nk-tint-pink: #2e2328;--nk-color-pink: #d15796;--nk-tint-red: #332523;--nk-color-red: #df5452;--nk-shadow-menu: rgba(15,15,15,.2) 0px 0px 0px 1px, rgba(15,15,15,.4) 0px 3px 6px, rgba(15,15,15,.6) 0px 9px 24px;--nk-shadow-card: none;--nk-shadow-btn: inset 0 0 0 1px rgba(255,255,255,.1), 0 1px 2px rgba(0,0,0,.3)}";
|
|
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: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-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-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{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}.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";
|
|
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,margin-left .24s cubic-bezier(.2,.8,.25,1)}.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-sidebar.collapsed{margin-left:calc(0px - var(--nk-sidebar-width) - env(safe-area-inset-left,0px));visibility:hidden;transition:background .25s ease,margin-left .24s cubic-bezier(.2,.8,.25,1),visibility 0s linear .24s}.nk-sidebar-toggle.collapsed{display:inline-flex}.nk-sidebar-head{display:flex;align-items:center}.nk-sidebar-head>.nk-workspace,.nk-sidebar-head ::slotted(.nk-workspace){flex:1;min-width:0}.nk-sidebar-collapse{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;margin:4px 12px 0 -4px;padding:0;border:none;border-radius:var(--nk-radius);background:transparent;color:var(--nk-text-tertiary);cursor:pointer;opacity:0;transition:opacity .15s}.nk-sidebar:hover .nk-sidebar-collapse,.nk-sidebar-collapse:focus-visible{opacity:1}.nk-sidebar-collapse:hover{background:var(--nk-bg-hover);color:var(--nk-text)}.nk-sidebar-collapse svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.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-dialog-backdrop{position:fixed;inset:0;z-index:105;display:none;align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top,0px)) max(16px,env(safe-area-inset-right,0px)) max(16px,env(safe-area-inset-bottom,0px)) max(16px,env(safe-area-inset-left,0px));background:var(--nk-scrim-soft);opacity:0;transition:opacity .2s ease,display .2s allow-discrete}.nk-dialog-backdrop.open{display:flex;opacity:1}@starting-style{.nk-dialog-backdrop.open{opacity:0}}.nk-dialog{width:440px;max-width:100%;max-height:100%;overflow-y:auto;overscroll-behavior:contain;padding:20px 24px;border-radius:10px;outline:none;background:var(--nk-bg);color:var(--nk-text);box-shadow:var(--nk-shadow-menu);scale:.98;translate:0 6px;transition:scale .2s ease,translate .2s ease}.nk-dialog.wide{width:560px}.nk-dialog-backdrop.open .nk-dialog{scale:1;translate:0 0}@starting-style{.nk-dialog-backdrop.open .nk-dialog{scale:.98;translate:0 6px}}.nk-dialog .dl-title{font-size:16px;font-weight:600;line-height:1.4;margin-bottom:6px}.nk-dialog .dl-body{font-size:14px;line-height:1.5}.nk-dialog .dl-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.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(var(--nk-peek-width),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-peek .pk-resize{position:absolute;top:0;bottom:0;left:-4px;width:8px;z-index:1;cursor:col-resize;touch-action:none;outline:none}.nk-peek .pk-resize:after{content:\"\";position:absolute;top:0;bottom:0;left:3px;width:2px;transition:background .15s}.nk-peek .pk-resize:hover:after,.nk-peek .pk-resize:focus-visible:after,.nk-peek .pk-resize.active:after{background:var(--nk-accent)}.nk-app.peek-inset .nk-main{padding-right:min(var(--nk-peek-width),100%)}.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-tooltip{z-index:130;max-width:260px;padding:4px 8px;border-radius:var(--nk-radius);background:var(--nk-text);color:var(--nk-bg);box-shadow:var(--nk-shadow-menu);font-size:12px;font-weight:500;line-height:16px;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .1s ease,visibility 0s linear .1s}.nk-tooltip.open{opacity:1;visibility:visible;transition:opacity .1s ease}.nk-tooltip .tt-key{margin-left:6px;color:color-mix(in srgb,var(--nk-bg) 60%,transparent)}.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-sidebar.collapsed{margin-left:0;visibility:visible;transition:background .25s ease,transform .24s cubic-bezier(.2,.8,.25,1),display .24s allow-discrete}.nk-sidebar-collapse{display:none}.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))}.nk-peek .pk-resize{display:none}.nk-app.peek-inset .nk-main{padding-right:0}.nk-dialog-backdrop{flex-direction:column;justify-content:flex-end;padding:max(24px,env(safe-area-inset-top,0px)) 0 0}.nk-dialog{width:100%;max-width:640px;border-radius:14px 14px 0 0;scale:none;translate:0 100%;padding:6px max(20px,env(safe-area-inset-right,0px)) max(16px,env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px));transition:translate .25s cubic-bezier(.2,.8,.2,1)}.nk-dialog.wide{width:100%}.nk-dialog-backdrop.open .nk-dialog{translate:0 0}@starting-style{.nk-dialog-backdrop.open .nk-dialog{translate:0 100%}}.nk-dialog:before{content:\"\";display:block;width:36px;height:4px;margin:4px auto 14px;border-radius:2px;background:var(--nk-border-strong)}.nk-dialog .dl-actions{flex-direction:column-reverse}: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;
|
|
@@ -368,7 +368,8 @@ class NkFormElement extends NkElement {
|
|
|
368
368
|
// <nk-btn variant="topbar">⭐</nk-btn> → <button class="nk-topbar-btn">
|
|
369
369
|
// <nk-btn variant="tool" active>Filter</nk-btn> → <button class="nk-db-tool active"> (slot="tools" of nk-database)
|
|
370
370
|
// <nk-btn variant="sidebar" aria-label="Menu">☰</nk-btn> → <button class="nk-topbar-btn nk-sidebar-toggle">:
|
|
371
|
-
//
|
|
371
|
+
// on a phone it opens the page's <nk-sidebar> as a drawer; on the desktop
|
|
372
|
+
// it shows while that sidebar is collapsed (.collapsed) and expands it.
|
|
372
373
|
//
|
|
373
374
|
// Modifier classes become attributes. A slotted <svg> is sized by the
|
|
374
375
|
// `.nk-btn ::slotted(svg)` twin; pass the icon itself, never wrapped.
|
|
@@ -414,11 +415,17 @@ class NkBtn extends NkElement {
|
|
|
414
415
|
|
|
415
416
|
/** The sidebar the ☰ opens: the one in its own app, else the page's. */
|
|
416
417
|
_sidebar() { return this.closest('nk-app')?.querySelector('nk-sidebar') ?? document.querySelector('nk-sidebar'); }
|
|
418
|
+
_sidebarCollapsed() { return this.getAttribute('variant') === 'sidebar' && !!this._sidebar()?.hasAttribute('collapsed'); }
|
|
417
419
|
|
|
418
420
|
setupEvents() {
|
|
419
421
|
this._onClick = (e) => {
|
|
420
422
|
if (this.getBoolAttr('disabled')) { e.preventDefault(); e.stopPropagation(); return; }
|
|
421
|
-
if (this.getAttribute('variant') === 'sidebar') {
|
|
423
|
+
if (this.getAttribute('variant') === 'sidebar') {
|
|
424
|
+
const sidebar = this._sidebar();
|
|
425
|
+
if (sidebar?.hasAttribute('collapsed') && !matchMedia('(max-width: 860px)').matches) sidebar.expand?.();
|
|
426
|
+
else sidebar?.toggle?.();
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
422
429
|
// A button inside a shadow root is not a submit button of the outer
|
|
423
430
|
// form; forward the intent to the form the host sits in.
|
|
424
431
|
const type = this.getAttribute('type');
|
|
@@ -431,13 +438,20 @@ class NkBtn extends NkElement {
|
|
|
431
438
|
this._onToggle = (e) => {
|
|
432
439
|
if (this.getAttribute('variant') === 'sidebar' && e.target === this._sidebar()) this._btn.setAttribute('aria-expanded', e.detail.open ? 'true' : 'false');
|
|
433
440
|
};
|
|
441
|
+
// On the desktop the ☰ shows while its sidebar is collapsed.
|
|
442
|
+
this._onCollapse = (e) => {
|
|
443
|
+
if (this.getAttribute('variant') === 'sidebar' && e.target === this._sidebar()) this._btn.classList.toggle('collapsed', e.detail.collapsed);
|
|
444
|
+
};
|
|
434
445
|
this._btn.addEventListener('click', this._onClick);
|
|
435
446
|
document.addEventListener('nk-toggle', this._onToggle);
|
|
447
|
+
document.addEventListener('nk-collapse', this._onCollapse);
|
|
448
|
+
if (this.getAttribute('variant') === 'sidebar') this._btn.className = this._computeClasses().join(' ');
|
|
436
449
|
}
|
|
437
450
|
|
|
438
451
|
teardownEvents() {
|
|
439
452
|
this._btn?.removeEventListener('click', this._onClick);
|
|
440
453
|
document.removeEventListener('nk-toggle', this._onToggle);
|
|
454
|
+
document.removeEventListener('nk-collapse', this._onCollapse);
|
|
441
455
|
}
|
|
442
456
|
|
|
443
457
|
onAttributeChanged(name) {
|
|
@@ -466,7 +480,7 @@ class NkBtn extends NkElement {
|
|
|
466
480
|
const variant = this.getAttribute('variant');
|
|
467
481
|
if (variant === 'topbar') return ['nk-topbar-btn'];
|
|
468
482
|
if (variant === 'share') return ['nk-topbar-btn', 'nk-share-btn'];
|
|
469
|
-
if (variant === 'sidebar') return ['nk-topbar-btn', 'nk-sidebar-toggle'];
|
|
483
|
+
if (variant === 'sidebar') return this._sidebarCollapsed() ? ['nk-topbar-btn', 'nk-sidebar-toggle', 'collapsed'] : ['nk-topbar-btn', 'nk-sidebar-toggle'];
|
|
470
484
|
if (variant === 'tool') return this.getBoolAttr('active') ? ['nk-db-tool', 'active'] : ['nk-db-tool'];
|
|
471
485
|
const classes = ['nk-btn'];
|
|
472
486
|
if (VARIANTS$1.includes(variant)) classes.push(variant);
|
|
@@ -1714,19 +1728,80 @@ customElements.define('nk-quote', NkQuote);
|
|
|
1714
1728
|
// </nk-app>
|
|
1715
1729
|
// → <div class="nk-app"><aside class="nk-sidebar">…</aside><main class="nk-main">…</main></div>
|
|
1716
1730
|
// The outermost element of a workspace app: a full-height flex row.
|
|
1731
|
+
// `peek-inset` (NotionKit 1.10.0) gives the main column a right padding as
|
|
1732
|
+
// wide as the side peek – <nk-peek inset> sets it while it is open.
|
|
1717
1733
|
class NkApp extends NkElement {
|
|
1734
|
+
static get observedAttributes() { return ['peek-inset']; }
|
|
1735
|
+
|
|
1718
1736
|
render() {
|
|
1719
|
-
const app = this.createElement('div', ['nk-app']);
|
|
1737
|
+
const app = this._app = this.createElement('div', ['nk-app']);
|
|
1738
|
+
app.classList.toggle('peek-inset', this.getBoolAttr('peek-inset'));
|
|
1720
1739
|
app.appendChild(this.createElement('slot', [], { name: 'sidebar' }));
|
|
1721
1740
|
const main = this.createElement('main', ['nk-main']);
|
|
1722
1741
|
main.appendChild(document.createElement('slot'));
|
|
1723
1742
|
app.appendChild(main);
|
|
1724
1743
|
this._wrapper.appendChild(app);
|
|
1725
1744
|
}
|
|
1745
|
+
|
|
1746
|
+
onAttributeChanged() { this._app.classList.toggle('peek-inset', this.getBoolAttr('peek-inset')); }
|
|
1726
1747
|
}
|
|
1727
1748
|
|
|
1728
1749
|
customElements.define('nk-app', NkApp);
|
|
1729
1750
|
|
|
1751
|
+
// Overlay plumbing shared by nk-modal, nk-sheet, nk-cmdk and nk-menu: body
|
|
1752
|
+
// scroll lock with a refcount, `inert` on everything outside the overlay so
|
|
1753
|
+
// focus and assistive technology stay inside – nested shadow roots included –
|
|
1754
|
+
// and the focused element behind shadow hosts, to return focus to.
|
|
1755
|
+
let locks = 0, previousOverflow = '';
|
|
1756
|
+
|
|
1757
|
+
function lockScroll() {
|
|
1758
|
+
if (locks++ === 0) {
|
|
1759
|
+
previousOverflow = document.documentElement.style.overflow;
|
|
1760
|
+
document.documentElement.style.overflow = 'hidden';
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
function unlockScroll() {
|
|
1765
|
+
if (locks > 0 && --locks === 0) document.documentElement.style.overflow = previousOverflow;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
/** Makes every sibling along `el`'s ancestor chain inert (shadow hosts included); returns the undo. */
|
|
1769
|
+
function inertOutside(el) {
|
|
1770
|
+
const made = [];
|
|
1771
|
+
let node = el;
|
|
1772
|
+
while (node && node !== document.body) {
|
|
1773
|
+
const parent = node.parentNode instanceof ShadowRoot ? node.parentNode : node.parentNode;
|
|
1774
|
+
if (!parent) break;
|
|
1775
|
+
for (const sib of parent.children) {
|
|
1776
|
+
if (sib === node || sib.inert || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(sib.tagName)) continue;
|
|
1777
|
+
sib.inert = true;
|
|
1778
|
+
made.push(sib);
|
|
1779
|
+
}
|
|
1780
|
+
node = parent instanceof ShadowRoot ? parent.host : parent;
|
|
1781
|
+
}
|
|
1782
|
+
return () => { for (const c of made) c.inert = false; };
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
/** The focused element itself, looking into shadow roots (document.activeElement stops at the host). */
|
|
1786
|
+
function deepActiveElement() {
|
|
1787
|
+
let el = document.activeElement;
|
|
1788
|
+
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
1789
|
+
return el;
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
/** The first tabbable element inside a light-DOM subtree, looking into shadow roots. */
|
|
1793
|
+
function firstFocusable(root) {
|
|
1794
|
+
const SEL = 'a[href], button:not([disabled]), input:not([disabled]):not([type=hidden]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable="true"], [contenteditable="plaintext-only"]';
|
|
1795
|
+
const walk = (node) => {
|
|
1796
|
+
for (const el of node.querySelectorAll('*')) {
|
|
1797
|
+
if (el.matches(SEL) && el.getClientRects().length) return el;
|
|
1798
|
+
if (el.shadowRoot) { const inner = walk(el.shadowRoot); if (inner) return inner; }
|
|
1799
|
+
}
|
|
1800
|
+
return null;
|
|
1801
|
+
};
|
|
1802
|
+
return walk(root);
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1730
1805
|
// <nk-sidebar slot="sidebar">
|
|
1731
1806
|
// <nk-workspace-switcher slot="workspace" name="Acme"></nk-workspace-switcher>
|
|
1732
1807
|
// <nk-tree>…</nk-tree>
|
|
@@ -1742,13 +1817,28 @@ customElements.define('nk-app', NkApp);
|
|
|
1742
1817
|
// .open) – the sidebar slides and the scrim fades by the same rules as the
|
|
1743
1818
|
// class markup; the element toggles the two classes. <nk-btn variant="sidebar">
|
|
1744
1819
|
// in the topbar is the ☰ that opens it.
|
|
1820
|
+
//
|
|
1821
|
+
// `collapsible` (NotionKit 1.10.0): on the desktop Notion's « beside the
|
|
1822
|
+
// workspace row collapses the sidebar – it slides out to the left, the main
|
|
1823
|
+
// column takes the width, nothing in it takes focus – and the topbar's ☰
|
|
1824
|
+
// brings it back; ⌘\ or Ctrl+\ toggles it (on a phone the drawer).
|
|
1825
|
+
// `collapsed` is the state, collapse() / expand() / toggleCollapsed() the
|
|
1826
|
+
// API, nk-collapse { collapsed } the moment to keep it. collapse-label names
|
|
1827
|
+
// the « (default "Close sidebar") and is its tooltip for <nk-tooltip>.
|
|
1828
|
+
const COLLAPSE_ICON = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m18 17-5-5 5-5M11 17l-5-5 5-5"/></svg>';
|
|
1829
|
+
const phone$1 = () => matchMedia('(max-width: 860px)').matches;
|
|
1830
|
+
|
|
1745
1831
|
class NkSidebar extends NkElement {
|
|
1746
|
-
static get observedAttributes() { return ['open']; }
|
|
1832
|
+
static get observedAttributes() { return ['open', 'collapsible', 'collapsed', 'collapse-label']; }
|
|
1747
1833
|
|
|
1748
1834
|
render() {
|
|
1749
1835
|
this._backdrop = this.createElement('div', ['nk-sidebar-backdrop']);
|
|
1750
1836
|
this._aside = this.createElement('aside', ['nk-sidebar']);
|
|
1751
|
-
this.
|
|
1837
|
+
const head = this.createElement('div', ['nk-sidebar-head']);
|
|
1838
|
+
this._collapse = this.createElement('button', ['nk-sidebar-collapse'], { type: 'button', 'data-tooltip-key': '⌘\\' });
|
|
1839
|
+
this._collapse.innerHTML = COLLAPSE_ICON;
|
|
1840
|
+
head.append(this.createElement('slot', [], { name: 'workspace' }), this._collapse);
|
|
1841
|
+
this._aside.appendChild(head);
|
|
1752
1842
|
const scroll = this.createElement('div', ['nk-sidebar-scroll']);
|
|
1753
1843
|
scroll.appendChild(document.createElement('slot'));
|
|
1754
1844
|
this._aside.appendChild(scroll);
|
|
@@ -1760,6 +1850,21 @@ class NkSidebar extends NkElement {
|
|
|
1760
1850
|
this._wrapper.appendChild(this._aside);
|
|
1761
1851
|
this._syncFooter();
|
|
1762
1852
|
this._syncOpen();
|
|
1853
|
+
this._syncCollapse();
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
_syncCollapse() {
|
|
1857
|
+
const label = this.getAttribute('collapse-label') || 'Close sidebar';
|
|
1858
|
+
this._collapse.hidden = !this.getBoolAttr('collapsible');
|
|
1859
|
+
this._collapse.setAttribute('aria-label', label);
|
|
1860
|
+
this._collapse.dataset.tooltip = label;
|
|
1861
|
+
this._aside.classList.toggle('collapsed', this.getBoolAttr('collapsed'));
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/** The ☰ that brings the sidebar back: the one in its own app, else the page's. */
|
|
1865
|
+
_toggleButton() {
|
|
1866
|
+
const sel = 'nk-btn[variant="sidebar"]';
|
|
1867
|
+
return this.closest('nk-app')?.querySelector(sel) ?? document.querySelector(sel);
|
|
1763
1868
|
}
|
|
1764
1869
|
|
|
1765
1870
|
_syncOpen() {
|
|
@@ -1779,22 +1884,47 @@ class NkSidebar extends NkElement {
|
|
|
1779
1884
|
setupEvents() {
|
|
1780
1885
|
this._onSlot = () => this._syncFooter();
|
|
1781
1886
|
this._onBackdrop = () => this.close();
|
|
1782
|
-
this._onKey = (e) => {
|
|
1887
|
+
this._onKey = (e) => {
|
|
1888
|
+
if (e.key === 'Escape' && this.getBoolAttr('open')) this.close();
|
|
1889
|
+
// Notion's ⌘\: the collapse on the desktop, the drawer on a phone.
|
|
1890
|
+
if (e.key === '\\' && (e.metaKey || e.ctrlKey) && this.getBoolAttr('collapsible') && !e.defaultPrevented) {
|
|
1891
|
+
e.preventDefault();
|
|
1892
|
+
phone$1() ? this.toggle() : this.toggleCollapsed();
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
this._onCollapse = () => this.collapse();
|
|
1783
1896
|
this._footerSlot.addEventListener('slotchange', this._onSlot);
|
|
1784
1897
|
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
1898
|
+
this._collapse.addEventListener('click', this._onCollapse);
|
|
1785
1899
|
document.addEventListener('keydown', this._onKey);
|
|
1786
1900
|
}
|
|
1787
1901
|
|
|
1788
1902
|
teardownEvents() {
|
|
1789
1903
|
this._footerSlot?.removeEventListener('slotchange', this._onSlot);
|
|
1790
1904
|
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
1905
|
+
this._collapse?.removeEventListener('click', this._onCollapse);
|
|
1791
1906
|
document.removeEventListener('keydown', this._onKey);
|
|
1792
1907
|
}
|
|
1793
1908
|
|
|
1794
1909
|
onAttributeChanged(name) {
|
|
1795
|
-
if (name
|
|
1796
|
-
|
|
1797
|
-
|
|
1910
|
+
if (name === 'open') {
|
|
1911
|
+
this._syncOpen();
|
|
1912
|
+
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
// Focus follows to the control that is left: the ☰ after collapsing, the « after expanding.
|
|
1916
|
+
const active = deepActiveElement();
|
|
1917
|
+
const fromSidebar = active && (this.contains(active) || this._shadow.contains(active));
|
|
1918
|
+
const fromToggle = active?.closest?.('.nk-sidebar-toggle');
|
|
1919
|
+
this._syncCollapse();
|
|
1920
|
+
if (name !== 'collapsed') return;
|
|
1921
|
+
const collapsed = this.getBoolAttr('collapsed');
|
|
1922
|
+
this.emit('nk-collapse', { collapsed });
|
|
1923
|
+
// Two frames later: with reduced motion every nk- element transitions for
|
|
1924
|
+
// .01ms, the inherited visibility included, so the « is focusable only then.
|
|
1925
|
+
const later = fn => requestAnimationFrame(() => requestAnimationFrame(fn));
|
|
1926
|
+
if (collapsed && fromSidebar) later(() => this._toggleButton()?.focus({ preventScroll: true }));
|
|
1927
|
+
if (!collapsed && fromToggle && !this._collapse.hidden) later(() => this._collapse.focus({ preventScroll: true }));
|
|
1798
1928
|
}
|
|
1799
1929
|
|
|
1800
1930
|
show() { this.setBoolAttr('open', true); }
|
|
@@ -1803,6 +1933,12 @@ class NkSidebar extends NkElement {
|
|
|
1803
1933
|
|
|
1804
1934
|
get open() { return this.getBoolAttr('open'); }
|
|
1805
1935
|
set open(v) { this.setBoolAttr('open', v); }
|
|
1936
|
+
|
|
1937
|
+
collapse() { this.setBoolAttr('collapsed', true); }
|
|
1938
|
+
expand() { this.setBoolAttr('collapsed', false); }
|
|
1939
|
+
toggleCollapsed() { this.setBoolAttr('collapsed', !this.getBoolAttr('collapsed')); }
|
|
1940
|
+
get collapsed() { return this.getBoolAttr('collapsed'); }
|
|
1941
|
+
set collapsed(v) { this.setBoolAttr('collapsed', v); }
|
|
1806
1942
|
}
|
|
1807
1943
|
|
|
1808
1944
|
customElements.define('nk-sidebar', NkSidebar);
|
|
@@ -1815,7 +1951,7 @@ customElements.define('nk-sidebar', NkSidebar);
|
|
|
1815
1951
|
// row; clicking outside or pressing Escape closes it.
|
|
1816
1952
|
const menuSheet = new CSSStyleSheet();
|
|
1817
1953
|
menuSheet.replaceSync(`
|
|
1818
|
-
.nk-ws-anchor { position: relative; }
|
|
1954
|
+
.nk-ws-anchor { position: relative; flex: 1 1 auto; min-width: 0; }
|
|
1819
1955
|
.nk-ws-menu { display: none; position: absolute; left: 8px; top: calc(100% - 2px); z-index: 50; }
|
|
1820
1956
|
:host([open]) .nk-ws-menu { display: block; }
|
|
1821
1957
|
`);
|
|
@@ -3706,60 +3842,6 @@ class NkPanel extends NkElement {
|
|
|
3706
3842
|
|
|
3707
3843
|
customElements.define('nk-panel', NkPanel);
|
|
3708
3844
|
|
|
3709
|
-
// Overlay plumbing shared by nk-modal, nk-sheet, nk-cmdk and nk-menu: body
|
|
3710
|
-
// scroll lock with a refcount, `inert` on everything outside the overlay so
|
|
3711
|
-
// focus and assistive technology stay inside – nested shadow roots included –
|
|
3712
|
-
// and the focused element behind shadow hosts, to return focus to.
|
|
3713
|
-
let locks = 0, previousOverflow = '';
|
|
3714
|
-
|
|
3715
|
-
function lockScroll() {
|
|
3716
|
-
if (locks++ === 0) {
|
|
3717
|
-
previousOverflow = document.documentElement.style.overflow;
|
|
3718
|
-
document.documentElement.style.overflow = 'hidden';
|
|
3719
|
-
}
|
|
3720
|
-
}
|
|
3721
|
-
|
|
3722
|
-
function unlockScroll() {
|
|
3723
|
-
if (locks > 0 && --locks === 0) document.documentElement.style.overflow = previousOverflow;
|
|
3724
|
-
}
|
|
3725
|
-
|
|
3726
|
-
/** Makes every sibling along `el`'s ancestor chain inert (shadow hosts included); returns the undo. */
|
|
3727
|
-
function inertOutside(el) {
|
|
3728
|
-
const made = [];
|
|
3729
|
-
let node = el;
|
|
3730
|
-
while (node && node !== document.body) {
|
|
3731
|
-
const parent = node.parentNode instanceof ShadowRoot ? node.parentNode : node.parentNode;
|
|
3732
|
-
if (!parent) break;
|
|
3733
|
-
for (const sib of parent.children) {
|
|
3734
|
-
if (sib === node || sib.inert || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(sib.tagName)) continue;
|
|
3735
|
-
sib.inert = true;
|
|
3736
|
-
made.push(sib);
|
|
3737
|
-
}
|
|
3738
|
-
node = parent instanceof ShadowRoot ? parent.host : parent;
|
|
3739
|
-
}
|
|
3740
|
-
return () => { for (const c of made) c.inert = false; };
|
|
3741
|
-
}
|
|
3742
|
-
|
|
3743
|
-
/** The focused element itself, looking into shadow roots (document.activeElement stops at the host). */
|
|
3744
|
-
function deepActiveElement() {
|
|
3745
|
-
let el = document.activeElement;
|
|
3746
|
-
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
3747
|
-
return el;
|
|
3748
|
-
}
|
|
3749
|
-
|
|
3750
|
-
/** The first tabbable element inside a light-DOM subtree, looking into shadow roots. */
|
|
3751
|
-
function firstFocusable(root) {
|
|
3752
|
-
const SEL = 'a[href], button:not([disabled]), input:not([disabled]):not([type=hidden]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable="true"], [contenteditable="plaintext-only"]';
|
|
3753
|
-
const walk = (node) => {
|
|
3754
|
-
for (const el of node.querySelectorAll('*')) {
|
|
3755
|
-
if (el.matches(SEL) && el.getClientRects().length) return el;
|
|
3756
|
-
if (el.shadowRoot) { const inner = walk(el.shadowRoot); if (inner) return inner; }
|
|
3757
|
-
}
|
|
3758
|
-
return null;
|
|
3759
|
-
};
|
|
3760
|
-
return walk(root);
|
|
3761
|
-
}
|
|
3762
|
-
|
|
3763
3845
|
// <nk-sheet id="more" title="More">
|
|
3764
3846
|
// <nk-tree manual>
|
|
3765
3847
|
// <nk-section-label>Favourites</nk-section-label>
|
|
@@ -4184,6 +4266,457 @@ class NkImagePicker extends NkElement {
|
|
|
4184
4266
|
|
|
4185
4267
|
customElements.define('nk-image-picker', NkImagePicker);
|
|
4186
4268
|
|
|
4269
|
+
// Calendar days for nk-calendar and nk-calendar-view: local days as
|
|
4270
|
+
// 'YYYY-MM-DD', no library. Weeks are ISO weeks (Monday-based, the week with
|
|
4271
|
+
// the year's first Thursday); the first weekday comes from the locale.
|
|
4272
|
+
const pad = n => String(n).padStart(2, '0');
|
|
4273
|
+
|
|
4274
|
+
const isoOf = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
4275
|
+
const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
4276
|
+
|
|
4277
|
+
/** 'YYYY-MM-DD[THH:MM]', 'D.M.YYYY', a Date or { start } → a local Date at midnight, or null. */
|
|
4278
|
+
function parseDay(v) {
|
|
4279
|
+
if (v instanceof Date) return Number.isNaN(v.getTime()) ? null : new Date(v.getFullYear(), v.getMonth(), v.getDate());
|
|
4280
|
+
if (v && typeof v === 'object') return v.start ? parseDay(v.start) : null;
|
|
4281
|
+
const s = String(v ?? '').trim();
|
|
4282
|
+
let m = s.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
|
4283
|
+
if (m) return new Date(+m[1], +m[2] - 1, +m[3]);
|
|
4284
|
+
m = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
|
|
4285
|
+
return m ? new Date(+m[3], +m[2] - 1, +m[1]) : null;
|
|
4286
|
+
}
|
|
4287
|
+
|
|
4288
|
+
function isoWeek(d) {
|
|
4289
|
+
const t = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
|
4290
|
+
t.setUTCDate(t.getUTCDate() + 4 - (t.getUTCDay() || 7));
|
|
4291
|
+
return Math.ceil(((t - Date.UTC(t.getUTCFullYear(), 0, 1)) / 864e5 + 1) / 7);
|
|
4292
|
+
}
|
|
4293
|
+
|
|
4294
|
+
/** The page's language unless the element names one. */
|
|
4295
|
+
const resolveLocale = attr => attr || document.documentElement.lang || navigator.language || 'en';
|
|
4296
|
+
|
|
4297
|
+
/** 0 = Sunday … 6 = Saturday, from Intl.Locale's week info; Monday where the browser cannot say. */
|
|
4298
|
+
function firstWeekday(locale) {
|
|
4299
|
+
try {
|
|
4300
|
+
const l = new Intl.Locale(locale), info = l.getWeekInfo?.() ?? l.weekInfo;
|
|
4301
|
+
if (info?.firstDay) return info.firstDay % 7;
|
|
4302
|
+
} catch { /* an unknown tag */ }
|
|
4303
|
+
return 1;
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
/** Short weekday names from `weekStart` on; `length` cuts them (2 → "Mo"). */
|
|
4307
|
+
function weekdayNames(locale, weekStart, length = 0) {
|
|
4308
|
+
const f = new Intl.DateTimeFormat(locale, { weekday: 'short' });
|
|
4309
|
+
// 7 June 2026 is a Sunday, so 7 + n is weekday n.
|
|
4310
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
4311
|
+
const name = f.format(new Date(2026, 5, 7 + ((weekStart + i) % 7))).replace('.', '');
|
|
4312
|
+
return length ? name.slice(0, length) : name;
|
|
4313
|
+
});
|
|
4314
|
+
}
|
|
4315
|
+
|
|
4316
|
+
/** A month from its week start: `first`, `day(i)` for the i-th cell, the `rows` it needs. */
|
|
4317
|
+
function monthGrid(month, weekStart) {
|
|
4318
|
+
const [y, m] = month.split('-').map(Number), first = new Date(y, m - 1, 1), offset = (first.getDay() - weekStart + 7) % 7;
|
|
4319
|
+
return { m, first, day: i => new Date(y, m - 1, 1 - offset + i), rows: Math.ceil((offset + new Date(y, m, 0).getDate()) / 7) };
|
|
4320
|
+
}
|
|
4321
|
+
|
|
4322
|
+
function stepMonth(month, n) {
|
|
4323
|
+
const [y, m] = month.split('-').map(Number);
|
|
4324
|
+
return isoOf(new Date(y, m - 1 + n, 1)).slice(0, 7);
|
|
4325
|
+
}
|
|
4326
|
+
|
|
4327
|
+
/** "KW" for German, "W" elsewhere – the head of the week column. */
|
|
4328
|
+
const weekLabel = locale => (/^de\b/i.test(locale) ? 'KW' : 'W');
|
|
4329
|
+
|
|
4330
|
+
const CHEVRONS = {
|
|
4331
|
+
prev: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg>',
|
|
4332
|
+
next: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>',
|
|
4333
|
+
};
|
|
4334
|
+
|
|
4335
|
+
// Placement for elements that float over the page – <nk-menu floating>,
|
|
4336
|
+
// <nk-calendar floating>: the host is a fixed box put under its anchor.
|
|
4337
|
+
|
|
4338
|
+
/** The border box of an element, or of the first descendant with one (display: contents hosts). */
|
|
4339
|
+
function boxOf(el) {
|
|
4340
|
+
if (el.getClientRects().length) return el.getBoundingClientRect();
|
|
4341
|
+
for (const child of [...(el.shadowRoot?.children ?? []), ...el.children]) {
|
|
4342
|
+
const r = boxOf(child);
|
|
4343
|
+
if (r.width || r.height) return r;
|
|
4344
|
+
}
|
|
4345
|
+
return el.getBoundingClientRect();
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
/**
|
|
4349
|
+
* Puts `host` 6px below `target` – an element or a rect ({ left, top, right,
|
|
4350
|
+
* bottom }, a DOMRect) – centred on it: above with side="top", or where the
|
|
4351
|
+
* window ends below; kept 8px inside the window. For <nk-tooltip>.
|
|
4352
|
+
*/
|
|
4353
|
+
function placeNear(host, target, side = 'bottom', gap = 6) {
|
|
4354
|
+
const r = target instanceof Element ? boxOf(target) : target;
|
|
4355
|
+
const { width: w, height: h } = host.getBoundingClientRect();
|
|
4356
|
+
const below = r.bottom + gap, above = r.top - gap - h;
|
|
4357
|
+
const top = side === 'top' ? (above < 8 ? below : above) : (below + h > innerHeight - 8 ? above : below);
|
|
4358
|
+
host.style.top = `${Math.round(top)}px`;
|
|
4359
|
+
host.style.left = `${Math.round(Math.min(Math.max(8, (r.left + r.right) / 2 - w / 2), innerWidth - 8 - w))}px`;
|
|
4360
|
+
host.style.right = '';
|
|
4361
|
+
}
|
|
4362
|
+
|
|
4363
|
+
/** Puts `host` 6px under `anchor`, right edges aligned – left edges with align="start". */
|
|
4364
|
+
function placeUnder(host, anchor, align) {
|
|
4365
|
+
const r = boxOf(anchor);
|
|
4366
|
+
host.style.top = `${r.bottom + 6}px`;
|
|
4367
|
+
if (align === 'start') { host.style.left = `${r.left}px`; host.style.right = ''; }
|
|
4368
|
+
else { host.style.right = `${Math.max(8, innerWidth - r.right)}px`; host.style.left = ''; }
|
|
4369
|
+
}
|
|
4370
|
+
|
|
4371
|
+
// <nk-calendar name="due" value="2026-06-02" weeks weekend="6,0"></nk-calendar>
|
|
4372
|
+
// <nk-calendar range value="2026-06-08/2026-06-12"></nk-calendar>
|
|
4373
|
+
// <nk-calendar floating sheet id="picker"></nk-calendar> picker.show(button)
|
|
4374
|
+
// → [<div class="nk-pop floating sheet open">]<div class="nk-calendar weeks">
|
|
4375
|
+
// <div class="cal-head"><div class="cal-title">June 2026</div><button class="cal-nav">Today</button>‹ ›</div>
|
|
4376
|
+
// <div class="cal-grid"><span class="cal-wd">W</span>…<span class="cal-week">23</span><button class="cal-day selected">2</button>…</div>
|
|
4377
|
+
// [<div class="cal-foot"><input class="nk-input" type="time"></div>]</div>
|
|
4378
|
+
//
|
|
4379
|
+
// Notion's date picker (NotionKit 1.9.0), after GlassKit Elements'
|
|
4380
|
+
// glk-calendar, with what a planning tool needs on top: a range, ISO
|
|
4381
|
+
// calendar weeks, days not worked, marks and a time.
|
|
4382
|
+
// value: YYYY-MM-DD; with `range` the ISO interval "start/end"; with `time`
|
|
4383
|
+
// YYYY-MM-DDTHH:MM. Also as the properties value, start, end.
|
|
4384
|
+
// month (YYYY-MM shown; default the value's, else today's), min, max, today,
|
|
4385
|
+
// locale (default the page's lang), week-start (0 = Sunday … 6 = Saturday;
|
|
4386
|
+
// default from the locale, Monday where the browser cannot say), weeks,
|
|
4387
|
+
// weekend (weekdays not worked, "6,0" for Saturday and Sunday), range, time,
|
|
4388
|
+
// clearable, label and the texts today-label, prev-label, next-label,
|
|
4389
|
+
// week-label, time-label, clear-label. `time` belongs to single days; a
|
|
4390
|
+
// range has none.
|
|
4391
|
+
// days (property, or JSON attribute): { 'YYYY-MM-DD': { off, label, marks } }
|
|
4392
|
+
// – `off` greys a holiday, `label` names the day (tooltip and screen
|
|
4393
|
+
// reader), `marks` puts up to three dots in the nine colours on it.
|
|
4394
|
+
// Keys: arrows by a day or a week, Home/End to the ends of the week,
|
|
4395
|
+
// PageUp/PageDown by a month (Shift: a year); Enter or Space picks. Arrows
|
|
4396
|
+
// only move, so the picker stays quiet while someone looks around. Days
|
|
4397
|
+
// outside min/max are aria-disabled – in the arrow path and announced, never
|
|
4398
|
+
// picked. A range takes two picks, in either order. Form-associated: the
|
|
4399
|
+
// value goes with the form, reset restores it.
|
|
4400
|
+
// Events: nk-change { value, start, end, time } when a pick – for a range the
|
|
4401
|
+
// second one –, a new time or Clear changes the value; nk-month { month } when the month
|
|
4402
|
+
// changes; nk-toggle { open } with `floating`. `required` makes an empty
|
|
4403
|
+
// value invalid.
|
|
4404
|
+
// `floating` makes it a popover over the page – show(anchor) puts it under
|
|
4405
|
+
// the anchor, right edges aligned (align="start": left edges) – and `sheet`
|
|
4406
|
+
// a bottom sheet with 44px cells on a phone, as <nk-menu floating sheet>.
|
|
4407
|
+
// A pick closes it – the second of a range; with `time` Escape or a tap
|
|
4408
|
+
// outside does. Put a floating calendar directly under <body>.
|
|
4409
|
+
const STEPS = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };
|
|
4410
|
+
const floatSheet$1 = new CSSStyleSheet();
|
|
4411
|
+
floatSheet$1.replaceSync(`:host([floating]) { display: block; position: fixed; z-index: 60; pointer-events: none; }`);
|
|
4412
|
+
|
|
4413
|
+
class NkCalendar extends NkFormElement {
|
|
4414
|
+
static get hostStyles() { return floatSheet$1; }
|
|
4415
|
+
static get observedAttributes() {
|
|
4416
|
+
return ['value', 'month', 'min', 'max', 'today', 'locale', 'week-start', 'weeks', 'weekend', 'range', 'time', 'clearable', 'days',
|
|
4417
|
+
'label', 'today-label', 'prev-label', 'next-label', 'week-label', 'time-label', 'clear-label', 'floating', 'sheet', 'open', 'align', 'required'];
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4420
|
+
render() {
|
|
4421
|
+
// A value or month set as a property before the first connect wins over the attributes.
|
|
4422
|
+
this._readValue(this._pendingValue ?? this.getAttribute('value'));
|
|
4423
|
+
const month = this._pendingMonth || this._attrMonth();
|
|
4424
|
+
if (month) this._month = month;
|
|
4425
|
+
this._initialValue = this.getAttribute('value') ?? '';
|
|
4426
|
+
this._build();
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
// ── value ──
|
|
4430
|
+
_readValue(v) {
|
|
4431
|
+
const s = String(v ?? '');
|
|
4432
|
+
this._start = this._end = this._day = null;
|
|
4433
|
+
this._time = '';
|
|
4434
|
+
if (this.getBoolAttr('range')) {
|
|
4435
|
+
const [a, b] = s.split('/');
|
|
4436
|
+
this._start = parseDay(a) ? isoOf(parseDay(a)) : null;
|
|
4437
|
+
this._end = parseDay(b) ? isoOf(parseDay(b)) : null;
|
|
4438
|
+
} else if (parseDay(s)) {
|
|
4439
|
+
this._day = isoOf(parseDay(s));
|
|
4440
|
+
this._time = s.match(/T(\d{2}:\d{2})/)?.[1] ?? '';
|
|
4441
|
+
}
|
|
4442
|
+
// A new value brings its month; without one the month stays.
|
|
4443
|
+
const shown = this._day || this._start;
|
|
4444
|
+
this._month = shown ? shown.slice(0, 7) : (this._month || this._attrMonth() || this._todayIso().slice(0, 7));
|
|
4445
|
+
this._focus = null;
|
|
4446
|
+
}
|
|
4447
|
+
|
|
4448
|
+
_attrMonth() { const m = this.getAttribute('month'); return /^\d{4}-\d{2}$/.test(m || '') ? m : null; }
|
|
4449
|
+
_todayIso() { return this.getAttribute('today') || isoOf(new Date()); }
|
|
4450
|
+
|
|
4451
|
+
get value() {
|
|
4452
|
+
if (this.getBoolAttr('range')) return this._start ? `${this._start}${this._end ? `/${this._end}` : ''}` : '';
|
|
4453
|
+
return this._day ? `${this._day}${this.getBoolAttr('time') && this._time ? `T${this._time}` : ''}` : '';
|
|
4454
|
+
}
|
|
4455
|
+
set value(v) {
|
|
4456
|
+
this._readValue(v);
|
|
4457
|
+
if (this._grid) this._draw(); else this._pendingValue = String(v ?? '');
|
|
4458
|
+
}
|
|
4459
|
+
get start() { return this.getBoolAttr('range') ? this._start : this._day; }
|
|
4460
|
+
get end() { return this.getBoolAttr('range') ? this._end : this._day; }
|
|
4461
|
+
get month() { return this._month; }
|
|
4462
|
+
set month(v) {
|
|
4463
|
+
if (!/^\d{4}-\d{2}$/.test(v)) return;
|
|
4464
|
+
this._month = v; this._focus = null;
|
|
4465
|
+
if (this._grid) this._draw(); else this._pendingMonth = v;
|
|
4466
|
+
}
|
|
4467
|
+
get days() { return this._days ?? {}; }
|
|
4468
|
+
set days(v) { this._days = v && typeof v === 'object' ? v : {}; if (this._grid) this._draw(); }
|
|
4469
|
+
|
|
4470
|
+
// ── markup ──
|
|
4471
|
+
_build() {
|
|
4472
|
+
const floating = this.getBoolAttr('floating');
|
|
4473
|
+
this._cal = this.createElement('div', ['nk-calendar'], { role: 'group' });
|
|
4474
|
+
const head = this.createElement('div', ['cal-head']);
|
|
4475
|
+
this._title = this.createElement('div', ['cal-title'], { 'aria-live': 'polite' });
|
|
4476
|
+
this._todayBtn = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4477
|
+
this._prev = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4478
|
+
this._prev.innerHTML = CHEVRONS.prev;
|
|
4479
|
+
this._next = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4480
|
+
this._next.innerHTML = CHEVRONS.next;
|
|
4481
|
+
head.append(this._title, this._todayBtn, this._prev, this._next);
|
|
4482
|
+
this._grid = this.createElement('div', ['cal-grid']);
|
|
4483
|
+
this._foot = this.createElement('div', ['cal-foot']);
|
|
4484
|
+
this._timeInput = this.createElement('input', ['nk-input'], { type: 'time' });
|
|
4485
|
+
this._clear = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
4486
|
+
this._cal.append(head, this._grid);
|
|
4487
|
+
this._pop = floating ? this.createElement('div', ['nk-pop', 'floating']) : null;
|
|
4488
|
+
if (this._pop) this._pop.appendChild(this._cal);
|
|
4489
|
+
this._wrapper.replaceChildren(this._pop ?? this._cal);
|
|
4490
|
+
this._draw();
|
|
4491
|
+
}
|
|
4492
|
+
|
|
4493
|
+
get _hasTime() { return this.getBoolAttr('time') && !this.getBoolAttr('range'); }
|
|
4494
|
+
get _locale() { return resolveLocale(this.getAttribute('locale')); }
|
|
4495
|
+
get _weekStart() {
|
|
4496
|
+
const n = Number(this.getAttribute('week-start'));
|
|
4497
|
+
return this.hasAttribute('week-start') && Number.isInteger(n) && n >= 0 && n <= 6 ? n : firstWeekday(this._locale);
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
_syncPop() {
|
|
4501
|
+
this._pop?.classList.toggle('sheet', this.getBoolAttr('sheet'));
|
|
4502
|
+
this._pop?.classList.toggle('open', this.getBoolAttr('open'));
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
_draw() {
|
|
4506
|
+
const locale = this._locale, ws = this._weekStart, weeks = this.getBoolAttr('weeks'), range = this.getBoolAttr('range');
|
|
4507
|
+
const g = monthGrid(this._month, ws), today = this._todayIso();
|
|
4508
|
+
const min = this.getAttribute('min') || '', max = this.getAttribute('max') || '';
|
|
4509
|
+
const weekend = new Set((this.getAttribute('weekend') || '').split(',').map(s => s.trim()).filter(Boolean).map(Number));
|
|
4510
|
+
let days = this._days;
|
|
4511
|
+
if (!days && this.hasAttribute('days')) { try { days = JSON.parse(this.getAttribute('days')); } catch { days = {}; } }
|
|
4512
|
+
days ??= {};
|
|
4513
|
+
const long = new Intl.DateTimeFormat(locale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
|
|
4514
|
+
this._cal.classList.toggle('weeks', weeks);
|
|
4515
|
+
this._syncPop();
|
|
4516
|
+
const label = this.getAttribute('label');
|
|
4517
|
+
if (label) this._cal.setAttribute('aria-label', label); else this._cal.removeAttribute('aria-label');
|
|
4518
|
+
this._title.textContent = new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(g.first);
|
|
4519
|
+
this._todayBtn.textContent = this.getAttribute('today-label') || 'Today';
|
|
4520
|
+
this._prev.setAttribute('aria-label', this.getAttribute('prev-label') || 'Previous month');
|
|
4521
|
+
this._next.setAttribute('aria-label', this.getAttribute('next-label') || 'Next month');
|
|
4522
|
+
|
|
4523
|
+
// The one tab stop: the focused day, else the chosen one, else the 1st.
|
|
4524
|
+
const cells = Array.from({ length: 42 }, (_, i) => isoOf(g.day(i)));
|
|
4525
|
+
const chosen = range ? this._start : this._day;
|
|
4526
|
+
if (!this._focus || !cells.includes(this._focus)) this._focus = cells.includes(chosen) ? chosen : `${this._month}-01`;
|
|
4527
|
+
|
|
4528
|
+
const nodes = [];
|
|
4529
|
+
if (weeks) nodes.push(this._head(this.getAttribute('week-label') || weekLabel(locale)));
|
|
4530
|
+
for (const w of weekdayNames(locale, ws, 2)) nodes.push(this._head(w));
|
|
4531
|
+
for (let i = 0; i < 42; i++) {
|
|
4532
|
+
const d = g.day(i), iso = cells[i], info = days[iso] || {};
|
|
4533
|
+
if (weeks && i % 7 === 0) { const wk = this.createElement('span', ['cal-week'], { 'aria-hidden': 'true' }); wk.textContent = isoWeek(d); nodes.push(wk); }
|
|
4534
|
+
const inRange = range && this._start && this._end && iso > this._start && iso < this._end;
|
|
4535
|
+
const cls = ['cal-day', d.getMonth() !== g.m - 1 && 'out', (weekend.has(d.getDay()) || info.off) && 'off', iso === today && 'today',
|
|
4536
|
+
!range && iso === this._day && 'selected', range && iso === this._start && 'start', range && iso === (this._end || this._start) && this._start && 'end', inRange && 'in-range'].filter(Boolean);
|
|
4537
|
+
const day = this.createElement('button', cls, { type: 'button', 'data-date': iso, tabindex: iso === this._focus ? '0' : '-1',
|
|
4538
|
+
'aria-pressed': String(cls.includes('selected') || cls.includes('start') || cls.includes('end')),
|
|
4539
|
+
'aria-label': `${long.format(d)}${info.label ? `, ${info.label}` : ''}` });
|
|
4540
|
+
if (info.label) day.title = info.label;
|
|
4541
|
+
if ((min && iso < min) || (max && iso > max)) day.setAttribute('aria-disabled', 'true');
|
|
4542
|
+
day.textContent = d.getDate();
|
|
4543
|
+
const marks = (info.marks || []).slice(0, 3);
|
|
4544
|
+
if (marks.length) {
|
|
4545
|
+
const m = this.createElement('span', ['cal-marks']);
|
|
4546
|
+
for (const tone of marks) m.appendChild(this.createElement('i', [tone]));
|
|
4547
|
+
day.appendChild(m);
|
|
4548
|
+
}
|
|
4549
|
+
nodes.push(day);
|
|
4550
|
+
}
|
|
4551
|
+
// The days are drawn anew; focus inside the grid moves to the new tab stop.
|
|
4552
|
+
const focused = this._grid.contains(this._shadow.activeElement);
|
|
4553
|
+
this._grid.replaceChildren(...nodes);
|
|
4554
|
+
if (focused) this.focusDay();
|
|
4555
|
+
|
|
4556
|
+
const time = this._hasTime, clearable = this.getBoolAttr('clearable');
|
|
4557
|
+
this._timeInput.value = this._time;
|
|
4558
|
+
this._timeInput.setAttribute('aria-label', this.getAttribute('time-label') || 'Time');
|
|
4559
|
+
this._clear.textContent = this.getAttribute('clear-label') || 'Clear';
|
|
4560
|
+
this._foot.replaceChildren(...[time && this._timeInput, clearable && this._clear].filter(Boolean));
|
|
4561
|
+
if (time || clearable) this._cal.appendChild(this._foot); else this._foot.remove();
|
|
4562
|
+
this._syncForm();
|
|
4563
|
+
}
|
|
4564
|
+
|
|
4565
|
+
_syncForm() {
|
|
4566
|
+
this.setFormValue(this.value);
|
|
4567
|
+
if (this.getBoolAttr('required') && !this.value) this.setValidity({ valueMissing: true }, 'Please choose a date.', this._grid?.querySelector('[tabindex="0"]') ?? undefined);
|
|
4568
|
+
else this.setValidity({});
|
|
4569
|
+
}
|
|
4570
|
+
|
|
4571
|
+
_head(text) {
|
|
4572
|
+
const s = this.createElement('span', ['cal-wd'], { 'aria-hidden': 'true' });
|
|
4573
|
+
s.textContent = text;
|
|
4574
|
+
return s;
|
|
4575
|
+
}
|
|
4576
|
+
|
|
4577
|
+
// ── interaction ──
|
|
4578
|
+
_goMonth(month, focus) {
|
|
4579
|
+
if (month !== this._month) { this._month = month; this.emit('nk-month', { month }); }
|
|
4580
|
+
this._focus = focus ?? null;
|
|
4581
|
+
this._draw();
|
|
4582
|
+
}
|
|
4583
|
+
|
|
4584
|
+
_pick(iso) {
|
|
4585
|
+
const day = this._grid.querySelector(`[data-date="${iso}"]`);
|
|
4586
|
+
if (day?.getAttribute('aria-disabled') === 'true') return;
|
|
4587
|
+
const before = this.value;
|
|
4588
|
+
let done = true;
|
|
4589
|
+
if (this.getBoolAttr('range')) {
|
|
4590
|
+
if (!this._start || this._end) { this._start = iso; this._end = null; done = false; }
|
|
4591
|
+
else if (iso < this._start) { this._end = this._start; this._start = iso; }
|
|
4592
|
+
else this._end = iso;
|
|
4593
|
+
} else this._day = iso;
|
|
4594
|
+
this._focus = iso;
|
|
4595
|
+
if (iso.slice(0, 7) !== this._month) this._goMonth(iso.slice(0, 7), iso); else this._draw();
|
|
4596
|
+
if (!done) return;
|
|
4597
|
+
// Only a new value is a change; the same day again just closes a popover.
|
|
4598
|
+
if (this.value !== before) this.emit('nk-change', { value: this.value, start: this.start, end: this.end, time: this._time || null });
|
|
4599
|
+
if (this.getBoolAttr('floating') && !this._hasTime) this.close();
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
setupEvents() {
|
|
4603
|
+
this._onGrid = (e) => { const day = e.target.closest('.cal-day'); if (day) this._pick(day.dataset.date); };
|
|
4604
|
+
this._onToday = () => { const t = this._todayIso(); this._goMonth(t.slice(0, 7), t); };
|
|
4605
|
+
this._onPrev = () => this._goMonth(stepMonth(this._month, -1));
|
|
4606
|
+
this._onNext = () => this._goMonth(stepMonth(this._month, 1));
|
|
4607
|
+
this._onKey = (e) => {
|
|
4608
|
+
// Enter and Space are the day button's own click.
|
|
4609
|
+
const day = e.target.closest?.('.cal-day');
|
|
4610
|
+
if (!day) return;
|
|
4611
|
+
const date = parseDay(day.dataset.date), ws = this._weekStart, wd = (date.getDay() - ws + 7) % 7;
|
|
4612
|
+
let target = null;
|
|
4613
|
+
if (STEPS[e.key]) target = addDays(date, STEPS[e.key]);
|
|
4614
|
+
else if (e.key === 'Home') target = addDays(date, -wd);
|
|
4615
|
+
else if (e.key === 'End') target = addDays(date, 6 - wd);
|
|
4616
|
+
else if (e.key === 'PageUp' || e.key === 'PageDown') {
|
|
4617
|
+
const months = (e.key === 'PageUp' ? -1 : 1) * (e.shiftKey ? 12 : 1);
|
|
4618
|
+
const last = new Date(date.getFullYear(), date.getMonth() + months + 1, 0).getDate();
|
|
4619
|
+
target = new Date(date.getFullYear(), date.getMonth() + months, Math.min(date.getDate(), last));
|
|
4620
|
+
}
|
|
4621
|
+
if (!target) return;
|
|
4622
|
+
e.preventDefault();
|
|
4623
|
+
const iso = isoOf(target);
|
|
4624
|
+
if (iso.slice(0, 7) !== this._month) this._goMonth(iso.slice(0, 7), iso);
|
|
4625
|
+
else { this._focus = iso; this._draw(); }
|
|
4626
|
+
};
|
|
4627
|
+
this._onTime = () => {
|
|
4628
|
+
this._time = this._timeInput.value;
|
|
4629
|
+
this._syncForm();
|
|
4630
|
+
if (this._day) this.emit('nk-change', { value: this.value, start: this.start, end: this.end, time: this._time || null });
|
|
4631
|
+
};
|
|
4632
|
+
this._onClear = () => {
|
|
4633
|
+
if (!this.value) return;
|
|
4634
|
+
this._day = this._start = this._end = null; this._time = '';
|
|
4635
|
+
this._draw();
|
|
4636
|
+
this.emit('nk-change', { value: '', start: null, end: null, time: null });
|
|
4637
|
+
};
|
|
4638
|
+
// Floating: a tap outside closes it and reaches nothing else; Escape closes (captured, before a modal around it).
|
|
4639
|
+
this._onOutside = (e) => {
|
|
4640
|
+
const path = e.composedPath();
|
|
4641
|
+
if (path.includes(this) || (this._anchor && path.includes(this._anchor))) return;
|
|
4642
|
+
e.preventDefault(); e.stopPropagation();
|
|
4643
|
+
this.close();
|
|
4644
|
+
};
|
|
4645
|
+
this._onEscape = (e) => { if (e.key === 'Escape' && this.getBoolAttr('floating') && this.getBoolAttr('open')) { e.stopPropagation(); this.close(); } };
|
|
4646
|
+
this._grid.addEventListener('click', this._onGrid);
|
|
4647
|
+
this._grid.addEventListener('keydown', this._onKey);
|
|
4648
|
+
this._todayBtn.addEventListener('click', this._onToday);
|
|
4649
|
+
this._prev.addEventListener('click', this._onPrev);
|
|
4650
|
+
this._next.addEventListener('click', this._onNext);
|
|
4651
|
+
this._timeInput.addEventListener('change', this._onTime);
|
|
4652
|
+
this._clear.addEventListener('click', this._onClear);
|
|
4653
|
+
document.addEventListener('keydown', this._onEscape, true);
|
|
4654
|
+
if (this.getBoolAttr('open')) document.addEventListener('click', this._onOutside, true);
|
|
4655
|
+
}
|
|
4656
|
+
|
|
4657
|
+
teardownEvents() {
|
|
4658
|
+
this._grid?.removeEventListener('click', this._onGrid);
|
|
4659
|
+
this._grid?.removeEventListener('keydown', this._onKey);
|
|
4660
|
+
this._todayBtn?.removeEventListener('click', this._onToday);
|
|
4661
|
+
this._prev?.removeEventListener('click', this._onPrev);
|
|
4662
|
+
this._next?.removeEventListener('click', this._onNext);
|
|
4663
|
+
this._timeInput?.removeEventListener('change', this._onTime);
|
|
4664
|
+
this._clear?.removeEventListener('click', this._onClear);
|
|
4665
|
+
document.removeEventListener('keydown', this._onEscape, true);
|
|
4666
|
+
document.removeEventListener('click', this._onOutside, true);
|
|
4667
|
+
}
|
|
4668
|
+
|
|
4669
|
+
onAttributeChanged(name, _old, value) {
|
|
4670
|
+
if (name === 'value') { this._readValue(value); this._draw(); return; }
|
|
4671
|
+
if (name === 'month') { this.month = value; return; }
|
|
4672
|
+
if (name === 'open' || name === 'sheet') { this._syncPop(); if (name === 'open') this._syncOpen(); return; }
|
|
4673
|
+
if (name === 'align') return;
|
|
4674
|
+
if (name === 'floating') { this.teardownEvents(); this._build(); if (this.isConnected) this.setupEvents(); return; }
|
|
4675
|
+
if (name === 'range') this._readValue(this.getAttribute('value'));
|
|
4676
|
+
if (name === 'days') this._days = null;
|
|
4677
|
+
this._draw();
|
|
4678
|
+
}
|
|
4679
|
+
|
|
4680
|
+
_syncOpen() {
|
|
4681
|
+
const open = this.getBoolAttr('open');
|
|
4682
|
+
if (this._anchor) (this._anchor.shadowRoot?.querySelector('button, a[href]') ?? this._anchor).setAttribute('aria-expanded', String(open));
|
|
4683
|
+
if (open) {
|
|
4684
|
+
this._returnFocus = deepActiveElement();
|
|
4685
|
+
if (this._returnFocus?.matches(':focus-visible')) requestAnimationFrame(() => this.focusDay());
|
|
4686
|
+
document.addEventListener('click', this._onOutside, true);
|
|
4687
|
+
} else {
|
|
4688
|
+
document.removeEventListener('click', this._onOutside, true);
|
|
4689
|
+
const back = this._returnFocus;
|
|
4690
|
+
this._returnFocus = null;
|
|
4691
|
+
const active = deepActiveElement();
|
|
4692
|
+
if (back?.isConnected && active && this._shadow.contains(active)) back.focus({ preventScroll: true });
|
|
4693
|
+
}
|
|
4694
|
+
this.emit('nk-toggle', { open });
|
|
4695
|
+
}
|
|
4696
|
+
|
|
4697
|
+
// ── form ──
|
|
4698
|
+
resetValue() { this._readValue(this._initialValue); this._draw(); }
|
|
4699
|
+
restoreValue(state) { this._readValue(state); this._draw(); }
|
|
4700
|
+
onFormDisabled(disabled) { this._cal?.toggleAttribute('inert', disabled); }
|
|
4701
|
+
|
|
4702
|
+
// ── API ──
|
|
4703
|
+
/** Opens under `anchor` (with `floating`), on the month of the value. */
|
|
4704
|
+
show(anchor) {
|
|
4705
|
+
if (anchor) { this._anchor = anchor; placeUnder(this, anchor, this.getAttribute('align')); }
|
|
4706
|
+
const shown = this.start;
|
|
4707
|
+
if (shown && shown.slice(0, 7) !== this._month) { this._month = shown.slice(0, 7); this._focus = null; this._draw(); }
|
|
4708
|
+
this.setBoolAttr('open', true);
|
|
4709
|
+
}
|
|
4710
|
+
close() { this.setBoolAttr('open', false); }
|
|
4711
|
+
toggle(anchor) { this.getBoolAttr('open') ? this.close() : this.show(anchor); }
|
|
4712
|
+
get open() { return this.getBoolAttr('open'); }
|
|
4713
|
+
set open(v) { this.setBoolAttr('open', v); }
|
|
4714
|
+
/** Moves focus to the day with the tab stop. */
|
|
4715
|
+
focusDay() { this._grid?.querySelector('[tabindex="0"]')?.focus(); }
|
|
4716
|
+
}
|
|
4717
|
+
|
|
4718
|
+
customElements.define('nk-calendar', NkCalendar);
|
|
4719
|
+
|
|
4187
4720
|
// <nk-peek id="peek" label="Database Table-View">
|
|
4188
4721
|
// <nk-btn slot="actions" variant="topbar" aria-label="Open as page"><svg …></svg></nk-btn>
|
|
4189
4722
|
// <nk-page-title>🗃️ Database Table-View</nk-page-title>
|
|
@@ -4203,17 +4736,28 @@ customElements.define('nk-image-picker', NkImagePicker);
|
|
|
4203
4736
|
// the peek) leave it open. Below 860px it is a bottom sheet over a dimmed
|
|
4204
4737
|
// page; there it is modal: the page is inert and scroll-locked, the dimmed
|
|
4205
4738
|
// page takes the tap that closes it. Put it directly under <body>.
|
|
4739
|
+
//
|
|
4740
|
+
// `resizable` (NotionKit 1.10.0): the left edge takes the pointer – and the
|
|
4741
|
+
// arrow keys, 16px a step – to make the peek wider or narrower, as in
|
|
4742
|
+
// Notion: from `min` (380) to `max` (all but 320px of the window). The width
|
|
4743
|
+
// is the token --nk-peek-width, set on :root; `width` (px) sets it too, and
|
|
4744
|
+
// nk-resize { width } fires when a drag or a key ends – the moment to keep
|
|
4745
|
+
// it. resize-label names the edge (default "Resize").
|
|
4746
|
+
// `inset`: while it is open on the desktop, the page's <nk-app> gets
|
|
4747
|
+
// `peek-inset` – its main column makes room instead of lying under the peek.
|
|
4206
4748
|
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>';
|
|
4207
|
-
const OVERLAYS = new Set(['nk-menu', 'nk-pop', 'nk-modal', 'nk-sheet', 'nk-cmdk', 'nk-toast']);
|
|
4208
|
-
const OVERLAY_CLASSES = ['nk-pop', 'nk-modal-backdrop', 'nk-sheet-backdrop', 'nk-cmdk-backdrop'];
|
|
4749
|
+
const OVERLAYS = new Set(['nk-menu', 'nk-pop', 'nk-modal', 'nk-sheet', 'nk-dialog', 'nk-cmdk', 'nk-toast']);
|
|
4750
|
+
const OVERLAY_CLASSES = ['nk-pop', 'nk-modal-backdrop', 'nk-sheet-backdrop', 'nk-dialog-backdrop', 'nk-cmdk-backdrop'];
|
|
4209
4751
|
const phone = () => matchMedia('(max-width: 860px)').matches;
|
|
4210
4752
|
|
|
4211
4753
|
class NkPeek extends NkElement {
|
|
4212
|
-
static get observedAttributes() { return ['open', 'label', 'close-label']; }
|
|
4754
|
+
static get observedAttributes() { return ['open', 'label', 'close-label', 'resizable', 'width', 'min', 'max', 'resize-label', 'inset']; }
|
|
4213
4755
|
|
|
4214
4756
|
render() {
|
|
4215
4757
|
this._backdrop = this.createElement('div', ['nk-peek-backdrop']);
|
|
4216
4758
|
this._box = this.createElement('aside', ['nk-peek'], { role: 'dialog', tabindex: '-1' });
|
|
4759
|
+
this._handle = this.createElement('div', ['pk-resize'], { role: 'separator', 'aria-orientation': 'vertical', tabindex: '0' });
|
|
4760
|
+
this._box.appendChild(this._handle);
|
|
4217
4761
|
const bar = this.createElement('div', ['pk-bar']);
|
|
4218
4762
|
this._close = this.createElement('button', ['nk-topbar-btn'], { type: 'button' });
|
|
4219
4763
|
this._close.innerHTML = CLOSE_ICON;
|
|
@@ -4224,9 +4768,41 @@ class NkPeek extends NkElement {
|
|
|
4224
4768
|
this._backdrop.appendChild(this._box);
|
|
4225
4769
|
this._wrapper.appendChild(this._backdrop);
|
|
4226
4770
|
this._syncLabels();
|
|
4771
|
+
this._syncResize();
|
|
4772
|
+
if (this.hasAttribute('width')) this._setWidth(Number(this.getAttribute('width')));
|
|
4227
4773
|
this._syncOpen();
|
|
4228
4774
|
}
|
|
4229
4775
|
|
|
4776
|
+
// ── width ──
|
|
4777
|
+
get _min() { return Number(this.getAttribute('min')) || 380; }
|
|
4778
|
+
get _max() { return Number(this.getAttribute('max')) || Math.max(this._min, innerWidth - 320); }
|
|
4779
|
+
/** The peek's width in px – the token --nk-peek-width. */
|
|
4780
|
+
get width() { return parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--nk-peek-width')) || 560; }
|
|
4781
|
+
set width(v) { this._setWidth(Number(v)); }
|
|
4782
|
+
|
|
4783
|
+
_setWidth(w) {
|
|
4784
|
+
if (!Number.isFinite(w)) return;
|
|
4785
|
+
w = Math.round(Math.min(Math.max(w, this._min), Math.max(this._min, this._max)));
|
|
4786
|
+
document.documentElement.style.setProperty('--nk-peek-width', `${w}px`);
|
|
4787
|
+
this._handle.setAttribute('aria-valuenow', w);
|
|
4788
|
+
}
|
|
4789
|
+
|
|
4790
|
+
_syncResize() {
|
|
4791
|
+
this._handle.hidden = !this.getBoolAttr('resizable');
|
|
4792
|
+
this._handle.setAttribute('aria-label', this.getAttribute('resize-label') || 'Resize');
|
|
4793
|
+
this._handle.setAttribute('aria-valuemin', this._min);
|
|
4794
|
+
this._handle.setAttribute('aria-valuenow', Math.round(this.width));
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
/** The app whose main column makes room: the peek's own, else the page's. */
|
|
4798
|
+
_app() { return this.closest('nk-app') ?? document.querySelector('nk-app'); }
|
|
4799
|
+
_syncInset() {
|
|
4800
|
+
const on = this.getBoolAttr('inset') && this.getBoolAttr('open') && !phone();
|
|
4801
|
+
if (on) this._app()?.setAttribute('peek-inset', '');
|
|
4802
|
+
else if (this._insetApp) this._app()?.removeAttribute('peek-inset');
|
|
4803
|
+
this._insetApp = on;
|
|
4804
|
+
}
|
|
4805
|
+
|
|
4230
4806
|
_syncLabels() {
|
|
4231
4807
|
const label = this.getAttribute('label');
|
|
4232
4808
|
if (label) this._box.setAttribute('aria-label', label); else this._box.removeAttribute('aria-label');
|
|
@@ -4236,6 +4812,7 @@ class NkPeek extends NkElement {
|
|
|
4236
4812
|
_syncOpen() {
|
|
4237
4813
|
const open = this.getBoolAttr('open');
|
|
4238
4814
|
this._backdrop.classList.toggle('open', open);
|
|
4815
|
+
this._syncInset();
|
|
4239
4816
|
if (open === this._wasOpen) return;
|
|
4240
4817
|
this._wasOpen = open;
|
|
4241
4818
|
if (open) {
|
|
@@ -4270,23 +4847,54 @@ class NkPeek extends NkElement {
|
|
|
4270
4847
|
if (path.some(n => n.nodeType === 1 && (OVERLAYS.has(n.localName) || OVERLAY_CLASSES.some(c => n.classList.contains(c))))) return;
|
|
4271
4848
|
this.close();
|
|
4272
4849
|
};
|
|
4850
|
+
// The left edge: a drag with pointer capture, or the arrow keys.
|
|
4851
|
+
const resized = () => this.emit('nk-resize', { width: Math.round(this.width) });
|
|
4852
|
+
this._onResizeStart = (e) => {
|
|
4853
|
+
if (e.button !== 0) return;
|
|
4854
|
+
e.preventDefault();
|
|
4855
|
+
this._handle.setPointerCapture(e.pointerId);
|
|
4856
|
+
this._handle.classList.add('active');
|
|
4857
|
+
};
|
|
4858
|
+
this._onResizeMove = (e) => { if (this._handle.hasPointerCapture(e.pointerId)) this._setWidth(innerWidth - e.clientX); };
|
|
4859
|
+
this._onResizeEnd = () => { this._handle.classList.remove('active'); resized(); };
|
|
4860
|
+
this._onResizeKey = (e) => {
|
|
4861
|
+
const step = { ArrowLeft: 16, ArrowRight: -16 }[e.key];
|
|
4862
|
+
if (!step) return;
|
|
4863
|
+
e.preventDefault();
|
|
4864
|
+
this._setWidth(this.width + step);
|
|
4865
|
+
resized();
|
|
4866
|
+
};
|
|
4867
|
+
this._onViewport = () => this._syncInset();
|
|
4273
4868
|
this._close.addEventListener('click', this._onClose);
|
|
4274
4869
|
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
4870
|
+
this._handle.addEventListener('pointerdown', this._onResizeStart);
|
|
4871
|
+
this._handle.addEventListener('pointermove', this._onResizeMove);
|
|
4872
|
+
this._handle.addEventListener('lostpointercapture', this._onResizeEnd);
|
|
4873
|
+
this._handle.addEventListener('keydown', this._onResizeKey);
|
|
4275
4874
|
document.addEventListener('keydown', this._onKey);
|
|
4276
4875
|
document.addEventListener('click', this._onOutside);
|
|
4876
|
+
addEventListener('resize', this._onViewport);
|
|
4277
4877
|
}
|
|
4278
4878
|
|
|
4279
4879
|
teardownEvents() {
|
|
4280
4880
|
this._close?.removeEventListener('click', this._onClose);
|
|
4281
4881
|
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
4882
|
+
this._handle?.removeEventListener('pointerdown', this._onResizeStart);
|
|
4883
|
+
this._handle?.removeEventListener('pointermove', this._onResizeMove);
|
|
4884
|
+
this._handle?.removeEventListener('lostpointercapture', this._onResizeEnd);
|
|
4885
|
+
this._handle?.removeEventListener('keydown', this._onResizeKey);
|
|
4282
4886
|
document.removeEventListener('keydown', this._onKey);
|
|
4283
4887
|
document.removeEventListener('click', this._onOutside);
|
|
4888
|
+
removeEventListener('resize', this._onViewport);
|
|
4889
|
+
if (this._insetApp) { this._app()?.removeAttribute('peek-inset'); this._insetApp = false; }
|
|
4284
4890
|
if (this._modal) { this._modal = false; unlockScroll(); this._undoInert?.(); this._undoInert = null; }
|
|
4285
4891
|
this._wasOpen = false;
|
|
4286
4892
|
}
|
|
4287
4893
|
|
|
4288
|
-
onAttributeChanged(name) {
|
|
4289
|
-
if (name
|
|
4894
|
+
onAttributeChanged(name, _old, value) {
|
|
4895
|
+
if (name === 'width') { this._setWidth(Number(value)); return; }
|
|
4896
|
+
if (name === 'inset') { this._syncInset(); return; }
|
|
4897
|
+
if (name !== 'open') { this._syncLabels(); this._syncResize(); return; }
|
|
4290
4898
|
this._syncOpen();
|
|
4291
4899
|
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
4292
4900
|
}
|
|
@@ -4301,6 +4909,283 @@ class NkPeek extends NkElement {
|
|
|
4301
4909
|
|
|
4302
4910
|
customElements.define('nk-peek', NkPeek);
|
|
4303
4911
|
|
|
4912
|
+
// <nk-dialog id="trash" title="Move “Roadmap” to trash?" alert>
|
|
4913
|
+
// The page and its sub-pages can be restored from Trash for 30 days.
|
|
4914
|
+
// <nk-btn slot="actions" variant="secondary" value="">Cancel</nk-btn>
|
|
4915
|
+
// <nk-btn slot="actions" variant="danger-solid" value="trash">Move to trash</nk-btn>
|
|
4916
|
+
// </nk-dialog>
|
|
4917
|
+
// → <div class="nk-dialog-backdrop open"><div class="nk-dialog" role="alertdialog">
|
|
4918
|
+
// <div class="dl-title">…</div><div class="dl-body">…</div><div class="dl-actions">…</div></div></div>
|
|
4919
|
+
//
|
|
4920
|
+
// A question or a short form (NotionKit 1.10.0) with the contract of
|
|
4921
|
+
// <nk-modal> and <nk-sheet>: show(), close(), toggle(), nk-toggle; Escape –
|
|
4922
|
+
// captured, so it closes before a peek, a menu or a modal behind it – and
|
|
4923
|
+
// the backdrop close it; focus moves in, to an [autofocus] element or the
|
|
4924
|
+
// first field or button, and back out; the page behind is inert and
|
|
4925
|
+
// scroll-locked. It lies above the modal and the sheet, so a question can
|
|
4926
|
+
// come from either. 440px, `wide` 560px; below 860px a bottom sheet with the
|
|
4927
|
+
// buttons stacked, the confirming one on top.
|
|
4928
|
+
// A button in slot="actions" with a `value` closes it with that value; so
|
|
4929
|
+
// does the submit of a <form method="dialog"> inside, with its submitter's
|
|
4930
|
+
// value. Before it closes, nk-close { value } fires and can be cancelled –
|
|
4931
|
+
// the place to check an input dialog; Escape and the backdrop close with ''.
|
|
4932
|
+
// `returnValue` keeps the last value. `alert` makes it an alertdialog, named
|
|
4933
|
+
// and described by its title and text. `title` is the heading, never a
|
|
4934
|
+
// tooltip – see NkElement.takeTitle(). Put it directly under <body>.
|
|
4935
|
+
class NkDialog extends NkElement {
|
|
4936
|
+
static get observedAttributes() { return ['open', 'title', 'wide', 'alert']; }
|
|
4937
|
+
|
|
4938
|
+
render() {
|
|
4939
|
+
this.takeTitle();
|
|
4940
|
+
this.returnValue = '';
|
|
4941
|
+
this._backdrop = this.createElement('div', ['nk-dialog-backdrop']);
|
|
4942
|
+
this._backdrop.inert = true;
|
|
4943
|
+
this._box = this.createElement('div', ['nk-dialog'], { 'aria-modal': 'true', tabindex: '-1' });
|
|
4944
|
+
this._heading = this.createElement('div', ['dl-title'], { id: 'title' });
|
|
4945
|
+
const body = this.createElement('div', ['dl-body'], { id: 'body' });
|
|
4946
|
+
body.appendChild(document.createElement('slot'));
|
|
4947
|
+
this._actions = this.createElement('div', ['dl-actions']);
|
|
4948
|
+
this._actionsSlot = this.createElement('slot', [], { name: 'actions' });
|
|
4949
|
+
this._actions.appendChild(this._actionsSlot);
|
|
4950
|
+
this._box.append(this._heading, body, this._actions);
|
|
4951
|
+
this._backdrop.appendChild(this._box);
|
|
4952
|
+
this._wrapper.appendChild(this._backdrop);
|
|
4953
|
+
this._syncTitle();
|
|
4954
|
+
this._syncMode();
|
|
4955
|
+
this._syncOpen();
|
|
4956
|
+
}
|
|
4957
|
+
|
|
4958
|
+
_syncTitle() {
|
|
4959
|
+
const text = this._titleText || '';
|
|
4960
|
+
this._heading.textContent = text;
|
|
4961
|
+
this._heading.hidden = !text;
|
|
4962
|
+
if (text) this._box.setAttribute('aria-labelledby', 'title');
|
|
4963
|
+
else this._box.removeAttribute('aria-labelledby');
|
|
4964
|
+
}
|
|
4965
|
+
|
|
4966
|
+
_syncMode() {
|
|
4967
|
+
const alert = this.getBoolAttr('alert');
|
|
4968
|
+
this._box.setAttribute('role', alert ? 'alertdialog' : 'dialog');
|
|
4969
|
+
if (alert) this._box.setAttribute('aria-describedby', 'body'); else this._box.removeAttribute('aria-describedby');
|
|
4970
|
+
this._box.classList.toggle('wide', this.getBoolAttr('wide'));
|
|
4971
|
+
}
|
|
4972
|
+
|
|
4973
|
+
_syncOpen() {
|
|
4974
|
+
const open = this.getBoolAttr('open');
|
|
4975
|
+
this._backdrop.classList.toggle('open', open);
|
|
4976
|
+
this._backdrop.inert = !open;
|
|
4977
|
+
if (open === this._wasOpen) return;
|
|
4978
|
+
this._wasOpen = open;
|
|
4979
|
+
if (open) {
|
|
4980
|
+
this._returnFocus = this._from ?? deepActiveElement();
|
|
4981
|
+
this._from = null;
|
|
4982
|
+
// An overlay behind – a modal – made this host inert; the dialog lifts that while it is open.
|
|
4983
|
+
this._wasInert = this.inert;
|
|
4984
|
+
this.inert = false;
|
|
4985
|
+
lockScroll();
|
|
4986
|
+
this._undoInert = inertOutside(this);
|
|
4987
|
+
requestAnimationFrame(() => (this.querySelector('[autofocus]') || firstFocusable(this) || this._box).focus({ preventScroll: true }));
|
|
4988
|
+
} else {
|
|
4989
|
+
unlockScroll();
|
|
4990
|
+
this._undoInert?.(); this._undoInert = null;
|
|
4991
|
+
this.inert = this._wasInert;
|
|
4992
|
+
const back = this._returnFocus;
|
|
4993
|
+
this._returnFocus = null;
|
|
4994
|
+
if (back?.isConnected && typeof back.focus === 'function') back.focus({ preventScroll: true });
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
|
|
4998
|
+
setupEvents() {
|
|
4999
|
+
this._onBackdrop = (e) => { if (e.target === this._backdrop) this.close(''); };
|
|
5000
|
+
this._onKey = (e) => { if (e.key === 'Escape' && this.getBoolAttr('open')) { e.stopPropagation(); this.close(''); } };
|
|
5001
|
+
// A button with a value closes it; a submit button is the form's.
|
|
5002
|
+
this._onClick = (e) => {
|
|
5003
|
+
const button = e.composedPath().find(n => n instanceof Element && n !== this && this.contains(n) && n.hasAttribute('value') && (n.localName === 'nk-btn' || n.localName === 'button'));
|
|
5004
|
+
if (!button || button.getAttribute('type') === 'submit') return;
|
|
5005
|
+
this.close(button.getAttribute('value'));
|
|
5006
|
+
};
|
|
5007
|
+
this._onSubmit = (e) => {
|
|
5008
|
+
if ((e.target.getAttribute('method') || '').toLowerCase() !== 'dialog') return;
|
|
5009
|
+
e.preventDefault();
|
|
5010
|
+
this.close(e.submitter?.value || e.submitter?.getAttribute?.('value') || 'submit');
|
|
5011
|
+
};
|
|
5012
|
+
this._onSlot = () => { this._actions.hidden = !this._actionsSlot.assignedElements().length; };
|
|
5013
|
+
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
5014
|
+
this.addEventListener('click', this._onClick);
|
|
5015
|
+
this.addEventListener('submit', this._onSubmit);
|
|
5016
|
+
this._actionsSlot.addEventListener('slotchange', this._onSlot);
|
|
5017
|
+
document.addEventListener('keydown', this._onKey, true);
|
|
5018
|
+
this._onSlot();
|
|
5019
|
+
}
|
|
5020
|
+
|
|
5021
|
+
teardownEvents() {
|
|
5022
|
+
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
5023
|
+
this.removeEventListener('click', this._onClick);
|
|
5024
|
+
this.removeEventListener('submit', this._onSubmit);
|
|
5025
|
+
this._actionsSlot?.removeEventListener('slotchange', this._onSlot);
|
|
5026
|
+
document.removeEventListener('keydown', this._onKey, true);
|
|
5027
|
+
if (this._wasOpen) { unlockScroll(); this._undoInert?.(); this._undoInert = null; this._wasOpen = false; }
|
|
5028
|
+
}
|
|
5029
|
+
|
|
5030
|
+
onAttributeChanged(name, oldValue, value) {
|
|
5031
|
+
if (name === 'title') { if (this.takeTitle(value)) this._syncTitle(); return; }
|
|
5032
|
+
if (name !== 'open') { this._syncMode(); return; }
|
|
5033
|
+
this._syncOpen();
|
|
5034
|
+
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5037
|
+
/** Opens it; focus goes back to `from` when it closes (default: what had focus – pass the ⋯ of a menu that closes). */
|
|
5038
|
+
show(from) { this.returnValue = ''; this._from = from ?? null; this.setBoolAttr('open', true); }
|
|
5039
|
+
/** Closes with `value`, unless an nk-close listener cancels it. Returns whether it closed. */
|
|
5040
|
+
close(value = '') {
|
|
5041
|
+
if (!this.getBoolAttr('open')) return false;
|
|
5042
|
+
if (!this.emit('nk-close', { value })) return false;
|
|
5043
|
+
this.returnValue = value;
|
|
5044
|
+
this.setBoolAttr('open', false);
|
|
5045
|
+
return true;
|
|
5046
|
+
}
|
|
5047
|
+
toggle() { this.getBoolAttr('open') ? this.close('') : this.show(); }
|
|
5048
|
+
|
|
5049
|
+
get open() { return this.getBoolAttr('open'); }
|
|
5050
|
+
set open(v) { v ? this.show() : this.close(''); }
|
|
5051
|
+
get title() { return this._titleText ?? ''; }
|
|
5052
|
+
set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._syncTitle(); }
|
|
5053
|
+
}
|
|
5054
|
+
|
|
5055
|
+
customElements.define('nk-dialog', NkDialog);
|
|
5056
|
+
|
|
5057
|
+
// <nk-tooltip></nk-tooltip> one for the page: every [data-tooltip]
|
|
5058
|
+
// <button data-tooltip="Close sidebar" data-tooltip-key="⌘\">«</button>
|
|
5059
|
+
// <nk-tooltip for="saveBtn" shortcut="⌘S">Save the page</nk-tooltip>
|
|
5060
|
+
// tip.show(barOrRect, 'Shell · 12.10.–30.11.'); tip.hide();
|
|
5061
|
+
// → <div class="nk-tooltip open" role="tooltip">Close sidebar<span class="tt-key">⌘\</span></div>
|
|
5062
|
+
//
|
|
5063
|
+
// Notion's hover hint (NotionKit 1.10.0). Without `for` it serves every
|
|
5064
|
+
// element with data-tooltip – and data-tooltip-key for a shortcut – on the
|
|
5065
|
+
// page, inside shadow roots too: the tooltips of a whole toolbar in one
|
|
5066
|
+
// element. With `for` it belongs to the element with that id and shows its
|
|
5067
|
+
// own content and `shortcut`. It appears after `delay` ms (400) under the
|
|
5068
|
+
// pointer and at once on keyboard focus, never on touch; leaving, a press,
|
|
5069
|
+
// blur, scrolling and Escape hide it. It sits 6px below its target and
|
|
5070
|
+
// centred, above it where the window ends – placement="top" prefers above –
|
|
5071
|
+
// and 8px inside the window (placeNear in util/floating.js). show(target,
|
|
5072
|
+
// text, shortcut) takes an element or a rect, for what has no element of
|
|
5073
|
+
// its own: the bars of a Gantt chart. While it shows, the target's
|
|
5074
|
+
// aria-describedby names it (in the same document or shadow root).
|
|
5075
|
+
const hostSheet = new CSSStyleSheet();
|
|
5076
|
+
hostSheet.replaceSync(`:host { display: block; position: fixed; top: 0; left: 0; z-index: 130; pointer-events: none; }`);
|
|
5077
|
+
let count = 0;
|
|
5078
|
+
|
|
5079
|
+
class NkTooltip extends NkElement {
|
|
5080
|
+
static get hostStyles() { return hostSheet; }
|
|
5081
|
+
static get observedAttributes() { return ['for', 'shortcut']; }
|
|
5082
|
+
|
|
5083
|
+
render() {
|
|
5084
|
+
this._bubble = this.createElement('div', ['nk-tooltip'], { role: 'tooltip' });
|
|
5085
|
+
this._slot = document.createElement('slot');
|
|
5086
|
+
this._text = document.createTextNode('');
|
|
5087
|
+
this._key = this.createElement('span', ['tt-key']);
|
|
5088
|
+
this._bubble.append(this._slot, this._text, this._key);
|
|
5089
|
+
this._wrapper.appendChild(this._bubble);
|
|
5090
|
+
this._fill(null);
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
get _delay() { const d = Number(this.getAttribute('delay')); return this.hasAttribute('delay') && d >= 0 ? d : 400; }
|
|
5094
|
+
|
|
5095
|
+
/** Own content (text null) or a given text and shortcut. */
|
|
5096
|
+
_fill(text, key = this.getAttribute('shortcut')) {
|
|
5097
|
+
this._slot.style.display = text == null ? '' : 'none';
|
|
5098
|
+
this._text.data = text ?? '';
|
|
5099
|
+
this._key.textContent = key || '';
|
|
5100
|
+
this._key.hidden = !key;
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5103
|
+
/** Shows it at `target` – an element or a rect – with `text` (else its own content) and `shortcut`. */
|
|
5104
|
+
show(target, text, shortcut) {
|
|
5105
|
+
clearTimeout(this._timer);
|
|
5106
|
+
if (!target) return;
|
|
5107
|
+
this._fill(text ?? null, shortcut);
|
|
5108
|
+
this._describe(target);
|
|
5109
|
+
placeNear(this, target, this.getAttribute('placement') === 'top' ? 'top' : 'bottom');
|
|
5110
|
+
this._bubble.classList.add('open');
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5113
|
+
hide() {
|
|
5114
|
+
clearTimeout(this._timer);
|
|
5115
|
+
this._bubble?.classList.remove('open');
|
|
5116
|
+
this._describe(null);
|
|
5117
|
+
this._target = null;
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5120
|
+
get open() { return !!this._bubble?.classList.contains('open'); }
|
|
5121
|
+
|
|
5122
|
+
_describe(target) {
|
|
5123
|
+
if (this._described) {
|
|
5124
|
+
const ids = (this._described.getAttribute('aria-describedby') || '').split(/\s+/).filter(id => id && id !== this.id);
|
|
5125
|
+
ids.length ? this._described.setAttribute('aria-describedby', ids.join(' ')) : this._described.removeAttribute('aria-describedby');
|
|
5126
|
+
this._described = null;
|
|
5127
|
+
}
|
|
5128
|
+
if (!(target instanceof Element) || target.getRootNode() !== this.getRootNode()) return;
|
|
5129
|
+
this.id ||= `nk-tooltip-${++count}`;
|
|
5130
|
+
const ids = (target.getAttribute('aria-describedby') || '').split(/\s+/).filter(Boolean);
|
|
5131
|
+
if (!ids.includes(this.id)) target.setAttribute('aria-describedby', [...ids, this.id].join(' '));
|
|
5132
|
+
this._described = target;
|
|
5133
|
+
}
|
|
5134
|
+
|
|
5135
|
+
/** The element this tooltip serves for an event: its `for` target, or the nearest [data-tooltip]. */
|
|
5136
|
+
_targetOf(e) {
|
|
5137
|
+
const path = e.composedPath();
|
|
5138
|
+
const own = this.getAttribute('for');
|
|
5139
|
+
if (own) { const el = this.getRootNode().getElementById?.(own); return el && path.includes(el) ? el : null; }
|
|
5140
|
+
return path.find(n => n instanceof Element && n.hasAttribute('data-tooltip')) ?? null;
|
|
5141
|
+
}
|
|
5142
|
+
|
|
5143
|
+
_showFor(el) {
|
|
5144
|
+
const own = this.hasAttribute('for');
|
|
5145
|
+
this.show(el, own ? null : el.getAttribute('data-tooltip'), own ? this.getAttribute('shortcut') : el.getAttribute('data-tooltip-key'));
|
|
5146
|
+
}
|
|
5147
|
+
|
|
5148
|
+
setupEvents() {
|
|
5149
|
+
this._onOver = (e) => {
|
|
5150
|
+
const el = e.pointerType === 'touch' ? null : this._targetOf(e);
|
|
5151
|
+
if (el === this._target) return;
|
|
5152
|
+
this.hide();
|
|
5153
|
+
if (!el) return;
|
|
5154
|
+
this._target = el;
|
|
5155
|
+
this._timer = setTimeout(() => this._showFor(el), this._delay);
|
|
5156
|
+
};
|
|
5157
|
+
this._onFocus = (e) => {
|
|
5158
|
+
const el = this._targetOf(e);
|
|
5159
|
+
if (!el || !deepActiveElement()?.matches(':focus-visible')) return;
|
|
5160
|
+
this.hide();
|
|
5161
|
+
this._target = el;
|
|
5162
|
+
this._showFor(el);
|
|
5163
|
+
};
|
|
5164
|
+
this._onHide = () => this.hide();
|
|
5165
|
+
this._onKey = (e) => { if (e.key === 'Escape' && this.open) this.hide(); };
|
|
5166
|
+
document.addEventListener('pointerover', this._onOver);
|
|
5167
|
+
document.addEventListener('focusin', this._onFocus);
|
|
5168
|
+
document.addEventListener('focusout', this._onHide);
|
|
5169
|
+
document.addEventListener('pointerdown', this._onHide, true);
|
|
5170
|
+
document.addEventListener('scroll', this._onHide, true);
|
|
5171
|
+
document.addEventListener('keydown', this._onKey);
|
|
5172
|
+
}
|
|
5173
|
+
|
|
5174
|
+
teardownEvents() {
|
|
5175
|
+
document.removeEventListener('pointerover', this._onOver);
|
|
5176
|
+
document.removeEventListener('focusin', this._onFocus);
|
|
5177
|
+
document.removeEventListener('focusout', this._onHide);
|
|
5178
|
+
document.removeEventListener('pointerdown', this._onHide, true);
|
|
5179
|
+
document.removeEventListener('scroll', this._onHide, true);
|
|
5180
|
+
document.removeEventListener('keydown', this._onKey);
|
|
5181
|
+
this.hide();
|
|
5182
|
+
}
|
|
5183
|
+
|
|
5184
|
+
onAttributeChanged(name) { if (name === 'shortcut' && !this._text.data) this._fill(null); if (name === 'for') this.hide(); }
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5187
|
+
customElements.define('nk-tooltip', NkTooltip);
|
|
5188
|
+
|
|
4304
5189
|
// <nk-modal id="settings">
|
|
4305
5190
|
// <nk-settings-user slot="user" name="…" mail="…"></nk-settings-user>
|
|
4306
5191
|
// <nk-settings-pane name="profile" group="Account" icon="👤" label="My profile" title="My profile" active>…</nk-settings-pane>
|
|
@@ -4774,16 +5659,6 @@ customElements.define('nk-cmdk', NkCmdk);
|
|
|
4774
5659
|
const floatSheet = new CSSStyleSheet();
|
|
4775
5660
|
floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; z-index: 60; pointer-events: none; }`);
|
|
4776
5661
|
|
|
4777
|
-
/** The border box of an element, or of the first descendant with one (display: contents hosts). */
|
|
4778
|
-
function boxOf(el) {
|
|
4779
|
-
if (el.getClientRects().length) return el.getBoundingClientRect();
|
|
4780
|
-
for (const child of [...(el.shadowRoot?.children ?? []), ...el.children]) {
|
|
4781
|
-
const r = boxOf(child);
|
|
4782
|
-
if (r.width || r.height) return r;
|
|
4783
|
-
}
|
|
4784
|
-
return el.getBoundingClientRect();
|
|
4785
|
-
}
|
|
4786
|
-
|
|
4787
5662
|
class NkMenu extends NkElement {
|
|
4788
5663
|
static get hostStyles() { return floatSheet; }
|
|
4789
5664
|
static get observedAttributes() { return ['floating', 'sheet', 'open', 'align']; }
|
|
@@ -4824,10 +5699,7 @@ class NkMenu extends NkElement {
|
|
|
4824
5699
|
show(anchor) {
|
|
4825
5700
|
if (anchor) {
|
|
4826
5701
|
this._anchor = anchor;
|
|
4827
|
-
|
|
4828
|
-
this.style.top = `${r.bottom + 6}px`;
|
|
4829
|
-
if (this.getAttribute('align') === 'start') { this.style.left = `${r.left}px`; this.style.right = ''; }
|
|
4830
|
-
else { this.style.right = `${Math.max(8, innerWidth - r.right)}px`; this.style.left = ''; }
|
|
5702
|
+
placeUnder(this, anchor, this.getAttribute('align'));
|
|
4831
5703
|
}
|
|
4832
5704
|
this.setBoolAttr('open', true);
|
|
4833
5705
|
}
|
|
@@ -5435,8 +6307,10 @@ function compareBy(column, dir = 1) {
|
|
|
5435
6307
|
// `wrap` lets cell text break (`.nk-table.wrap`), like Notion's "wrap column".
|
|
5436
6308
|
// Standalone: view.columns = […]; view.rows = […]; Inside <nk-database> the
|
|
5437
6309
|
// database pushes `data`. → <div class="nk-table-wrap"><table class="nk-table">…</table><div class="nk-new-row">+ New page</div></div>
|
|
5438
|
-
// Cells are plain markup from renderPropertyCell(); rows fire nk-select
|
|
5439
|
-
//
|
|
6310
|
+
// Cells are plain markup from renderPropertyCell(); rows fire nk-select
|
|
6311
|
+
// { row, id, key, cell } – `key` and `cell` say which cell was hit, to open
|
|
6312
|
+
// an editor there, like the date picker under a due date – checkboxes
|
|
6313
|
+
// nk-change, headers nk-action { action: 'sort' } (and sort locally
|
|
5440
6314
|
// with `sortable`), the add row nk-action { action: 'new-row' }.
|
|
5441
6315
|
class NkTableView extends NkElement {
|
|
5442
6316
|
static get observedAttributes() { return ['name', 'label', 'badge', 'count', 'new-row', 'new-row-label', 'sortable', 'sort-key', 'sort-dir', 'wrap']; }
|
|
@@ -5504,7 +6378,11 @@ class NkTableView extends NkElement {
|
|
|
5504
6378
|
}
|
|
5505
6379
|
if (e.target.closest('input[type=checkbox], a')) return;
|
|
5506
6380
|
const tr = e.target.closest('tr[data-id]');
|
|
5507
|
-
if (tr)
|
|
6381
|
+
if (!tr) return;
|
|
6382
|
+
// Which cell: `key` names its column, `cell` is there to anchor an editor to.
|
|
6383
|
+
const cell = e.target.closest('td');
|
|
6384
|
+
const row = this._rowById(tr.dataset.id);
|
|
6385
|
+
this.emit('nk-select', { row, id: row?.id, value: row?.id, key: cell ? this._columns[cell.cellIndex]?.key : undefined, cell });
|
|
5508
6386
|
};
|
|
5509
6387
|
this._onChange = (e) => {
|
|
5510
6388
|
const input = e.target;
|
|
@@ -5755,6 +6633,139 @@ class NkListView extends NkElement {
|
|
|
5755
6633
|
|
|
5756
6634
|
customElements.define('nk-list-view', NkListView);
|
|
5757
6635
|
|
|
6636
|
+
// <nk-calendar-view name="calendar" label="📅 Calendar" date-key="due" weeks></nk-calendar-view>
|
|
6637
|
+
// The fourth database view (NotionKit 1.9.0): a month, the rows as cards on
|
|
6638
|
+
// their dates. `date-key` names the date column (default: the first one),
|
|
6639
|
+
// `title-key` the title (default: the title column); dates are YYYY-MM-DD or
|
|
6640
|
+
// D.M.YYYY, a range { start, end } stands on its start. month (YYYY-MM;
|
|
6641
|
+
// default today's), weeks (the ISO week in front of each row), week-start
|
|
6642
|
+
// (0 = Sunday … 6 = Saturday; default from the locale), weekend (weekdays
|
|
6643
|
+
// washed like the days of other months, "6,0"), today, locale and the texts
|
|
6644
|
+
// today-label, prev-label, next-label, week-label.
|
|
6645
|
+
// Standalone: view.columns = […]; view.rows = […]. Inside <nk-database> the
|
|
6646
|
+
// database pushes the data. A card fires nk-select { row, id, value } like a
|
|
6647
|
+
// row of the table, Today and ‹ › nk-month { month }.
|
|
6648
|
+
// → <div class="nk-calendar-view weeks"><div class="cv-head"><div class="cv-title">May 2026</div><button class="cal-nav">Today</button>‹ ›</div>
|
|
6649
|
+
// <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>
|
|
6650
|
+
class NkCalendarView extends NkElement {
|
|
6651
|
+
static get observedAttributes() {
|
|
6652
|
+
return ['name', 'label', 'badge', 'count', 'date-key', 'title-key', 'month', 'weeks', 'week-start', 'weekend', 'today', 'locale',
|
|
6653
|
+
'today-label', 'prev-label', 'next-label', 'week-label'];
|
|
6654
|
+
}
|
|
6655
|
+
|
|
6656
|
+
render() {
|
|
6657
|
+
this._box = this.createElement('div', ['nk-calendar-view']);
|
|
6658
|
+
const head = this.createElement('div', ['cv-head']);
|
|
6659
|
+
this._title = this.createElement('div', ['cv-title']);
|
|
6660
|
+
this._todayBtn = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6661
|
+
this._prev = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6662
|
+
this._prev.innerHTML = CHEVRONS.prev;
|
|
6663
|
+
this._next = this.createElement('button', ['cal-nav'], { type: 'button' });
|
|
6664
|
+
this._next.innerHTML = CHEVRONS.next;
|
|
6665
|
+
head.append(this._title, this._todayBtn, this._prev, this._next);
|
|
6666
|
+
this._grid = this.createElement('div', ['cv-grid']);
|
|
6667
|
+
this._box.append(head, this._grid);
|
|
6668
|
+
this._wrapper.appendChild(this._box);
|
|
6669
|
+
this._columns ??= []; this._rows ??= [];
|
|
6670
|
+
this._month ??= this._attrMonth() ?? this._todayIso().slice(0, 7);
|
|
6671
|
+
this._render();
|
|
6672
|
+
this.closest('nk-database')?.requestSync?.();
|
|
6673
|
+
}
|
|
6674
|
+
|
|
6675
|
+
_attrMonth() { const m = this.getAttribute('month'); return /^\d{4}-\d{2}$/.test(m || '') ? m : null; }
|
|
6676
|
+
_todayIso() { return this.getAttribute('today') || isoOf(new Date()); }
|
|
6677
|
+
_dateColumn() {
|
|
6678
|
+
const key = this.getAttribute('date-key');
|
|
6679
|
+
return this._columns.find(c => c.key === key) || this._columns.find(c => c.type === 'date') || null;
|
|
6680
|
+
}
|
|
6681
|
+
_titleColumn() {
|
|
6682
|
+
const key = this.getAttribute('title-key');
|
|
6683
|
+
return this._columns.find(c => c.key === key) || this._columns.find(c => c.title) || this._columns[0] || null;
|
|
6684
|
+
}
|
|
6685
|
+
|
|
6686
|
+
_render() {
|
|
6687
|
+
if (!this._grid) return;
|
|
6688
|
+
const locale = resolveLocale(this.getAttribute('locale')), weeks = this.getBoolAttr('weeks');
|
|
6689
|
+
const n = Number(this.getAttribute('week-start'));
|
|
6690
|
+
const ws = this.hasAttribute('week-start') && Number.isInteger(n) && n >= 0 && n <= 6 ? n : firstWeekday(locale);
|
|
6691
|
+
const g = monthGrid(this._month, ws), today = this._todayIso();
|
|
6692
|
+
const weekend = new Set((this.getAttribute('weekend') || '').split(',').map(s => s.trim()).filter(Boolean).map(Number));
|
|
6693
|
+
const dateCol = this._dateColumn(), titleCol = this._titleColumn(), byDay = {};
|
|
6694
|
+
if (dateCol) for (const row of this._rows) {
|
|
6695
|
+
const d = parseDay(row[dateCol.key]);
|
|
6696
|
+
if (d) (byDay[isoOf(d)] ||= []).push(row);
|
|
6697
|
+
}
|
|
6698
|
+
this._box.classList.toggle('weeks', weeks);
|
|
6699
|
+
this._title.textContent = new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(g.first);
|
|
6700
|
+
this._todayBtn.textContent = this.getAttribute('today-label') || 'Today';
|
|
6701
|
+
this._prev.setAttribute('aria-label', this.getAttribute('prev-label') || 'Previous month');
|
|
6702
|
+
this._next.setAttribute('aria-label', this.getAttribute('next-label') || 'Next month');
|
|
6703
|
+
|
|
6704
|
+
const cell = (cls, text) => { const el = this.createElement('div', [cls]); el.textContent = text; return el; };
|
|
6705
|
+
const nodes = [];
|
|
6706
|
+
if (weeks) nodes.push(cell('cv-wd', this.getAttribute('week-label') || weekLabel(locale)));
|
|
6707
|
+
for (const w of weekdayNames(locale, ws)) nodes.push(cell('cv-wd', w));
|
|
6708
|
+
for (let i = 0; i < g.rows * 7; i++) {
|
|
6709
|
+
const d = g.day(i), iso = isoOf(d);
|
|
6710
|
+
if (weeks && i % 7 === 0) nodes.push(cell('cv-week', isoWeek(d)));
|
|
6711
|
+
const day = this.createElement('div', ['cv-day', d.getMonth() !== g.m - 1 && 'out', weekend.has(d.getDay()) && 'off', iso === today && 'today'].filter(Boolean));
|
|
6712
|
+
const num = this.createElement('span', ['cv-num']);
|
|
6713
|
+
num.textContent = d.getDate();
|
|
6714
|
+
day.appendChild(num);
|
|
6715
|
+
for (const row of byDay[iso] || []) {
|
|
6716
|
+
const item = this.createElement('button', ['cv-item'], { type: 'button', 'data-id': row.id ?? '' });
|
|
6717
|
+
const title = titleCol ? String(row[titleCol.key] ?? '') : '';
|
|
6718
|
+
item.textContent = row.icon ? `${row.icon} ${title}` : title;
|
|
6719
|
+
day.appendChild(item);
|
|
6720
|
+
}
|
|
6721
|
+
nodes.push(day);
|
|
6722
|
+
}
|
|
6723
|
+
this._grid.replaceChildren(...nodes);
|
|
6724
|
+
}
|
|
6725
|
+
|
|
6726
|
+
_goMonth(month) {
|
|
6727
|
+
if (month === this._month) return;
|
|
6728
|
+
this._month = month;
|
|
6729
|
+
this._render();
|
|
6730
|
+
this.emit('nk-month', { month });
|
|
6731
|
+
}
|
|
6732
|
+
|
|
6733
|
+
setupEvents() {
|
|
6734
|
+
this._onClick = (e) => {
|
|
6735
|
+
if (e.target.closest('.cal-nav') === this._todayBtn) { this._goMonth(this._todayIso().slice(0, 7)); return; }
|
|
6736
|
+
if (e.target.closest('.cal-nav') === this._prev) { this._goMonth(stepMonth(this._month, -1)); return; }
|
|
6737
|
+
if (e.target.closest('.cal-nav') === this._next) { this._goMonth(stepMonth(this._month, 1)); return; }
|
|
6738
|
+
const item = e.target.closest('.cv-item');
|
|
6739
|
+
if (item) { const row = this._rowById(item.dataset.id); this.emit('nk-select', { row, id: row?.id, value: row?.id }); }
|
|
6740
|
+
};
|
|
6741
|
+
this._box.addEventListener('click', this._onClick);
|
|
6742
|
+
}
|
|
6743
|
+
|
|
6744
|
+
teardownEvents() { this._box?.removeEventListener('click', this._onClick); }
|
|
6745
|
+
|
|
6746
|
+
_rowById(id) { return this._rows.find(r => String(r.id) === String(id)); }
|
|
6747
|
+
|
|
6748
|
+
onAttributeChanged(name) {
|
|
6749
|
+
if (name === 'month') this._month = this._attrMonth() ?? this._month;
|
|
6750
|
+
this._render();
|
|
6751
|
+
if (name === 'label' || name === 'badge' || name === 'count') this.closest('nk-database')?.requestSync?.();
|
|
6752
|
+
}
|
|
6753
|
+
|
|
6754
|
+
get name() { return this.getAttribute('name') || 'calendar'; }
|
|
6755
|
+
/** The month shown, YYYY-MM. */
|
|
6756
|
+
get month() { return this._month; }
|
|
6757
|
+
set month(v) { if (!/^\d{4}-\d{2}$/.test(v)) return; if (this._grid) this._goMonth(v); else this._month = v; }
|
|
6758
|
+
get columns() { return this._columns; }
|
|
6759
|
+
set columns(v) { this._columns = Array.isArray(v) ? v : []; this._render(); }
|
|
6760
|
+
get rows() { return this._rows; }
|
|
6761
|
+
set rows(v) { this._rows = Array.isArray(v) ? v : []; this._render(); }
|
|
6762
|
+
set data({ columns, rows }) { this.setData(columns, rows); }
|
|
6763
|
+
setData(columns, rows) { this._columns = columns || []; this._rows = rows || []; this._render(); }
|
|
6764
|
+
refresh() { this._render(); }
|
|
6765
|
+
}
|
|
6766
|
+
|
|
6767
|
+
customElements.define('nk-calendar-view', NkCalendarView);
|
|
6768
|
+
|
|
5758
6769
|
// <nk-filter-bar add no-filter no-sort></nk-filter-bar>
|
|
5759
6770
|
// bar.filters = [{ key: 'status', value: 'done', op: 'is-not', label: 'Status: Open' }];
|
|
5760
6771
|
// The filters in effect as NotionKit's filter pills (1.7.0), no inline style:
|
|
@@ -6079,4 +7090,4 @@ class NkAiInputRow extends NkElement {
|
|
|
6079
7090
|
|
|
6080
7091
|
customElements.define('nk-ai-input-row', NkAiInputRow);
|
|
6081
7092
|
|
|
6082
|
-
export { NkAiInputRow, NkAiMsg, NkAiThread, NkApp, NkAvatar, NkAvatarGroup, NkBanner, NkBlockHost, NkBoardView, NkBookmark, NkBreadcrumb, NkBtn, 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 };
|
|
7093
|
+
export { NkAiInputRow, NkAiMsg, NkAiThread, NkApp, NkAvatar, NkAvatarGroup, NkBanner, NkBlockHost, NkBoardView, NkBookmark, NkBreadcrumb, NkBtn, NkCalendar, NkCalendarView, NkCallout, NkCheck, NkCmdk, NkCode, NkComment, NkComments, NkCopyField, NkDangerZone, NkDatabase, NkDialog, 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, NkTooltip, NkTopbar, NkTree, NkTreeItem, NkWorkspaceSwitcher, compareBy, componentsSheet, renderPropertyCell, tagFor };
|