adminator-admin-dashboard 2.8.1 → 4.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/CHANGELOG.md +499 -0
  2. package/CLAUDE.md +126 -154
  3. package/README.md +321 -370
  4. package/dist/2026.js +8751 -0
  5. package/dist/2026.js.map +1 -0
  6. package/dist/404.html +36 -16
  7. package/dist/500.html +36 -16
  8. package/dist/assets/static/images/logo.svg +3 -3
  9. package/dist/basic-table.html +152 -699
  10. package/dist/blank.html +42 -507
  11. package/dist/buttons.html +152 -448
  12. package/dist/calendar.html +246 -658
  13. package/dist/charts.html +124 -658
  14. package/dist/chat.html +209 -706
  15. package/dist/compose.html +141 -618
  16. package/dist/datatable.html +467 -991
  17. package/dist/email.html +430 -943
  18. package/dist/forms.html +208 -733
  19. package/dist/google-maps.html +123 -513
  20. package/dist/index.html +436 -1041
  21. package/dist/runtime.js +1299 -0
  22. package/dist/runtime.js.map +1 -0
  23. package/dist/signin.html +92 -92
  24. package/dist/signup.html +106 -91
  25. package/dist/ui.html +268 -897
  26. package/dist/vector-maps.html +132 -511
  27. package/dist/vendor-chartjs.js +14593 -0
  28. package/dist/vendor-chartjs.js.map +1 -0
  29. package/dist/vendor-fullcalendar.js +14793 -0
  30. package/dist/vendor-fullcalendar.js.map +1 -0
  31. package/dist/vendors.js +3758 -0
  32. package/dist/vendors.js.map +1 -0
  33. package/package.json +50 -52
  34. package/src/404.html +35 -15
  35. package/src/500.html +35 -15
  36. package/src/assets/scripts/2026/Shell.js +312 -0
  37. package/src/assets/scripts/2026/calendar.js +123 -0
  38. package/src/assets/scripts/2026/charts.js +259 -0
  39. package/src/assets/scripts/2026/index.js +35 -0
  40. package/src/assets/scripts/2026/init.js +207 -0
  41. package/src/assets/scripts/2026/maps.js +78 -0
  42. package/src/assets/scripts/2026/palette.js +266 -0
  43. package/src/assets/static/images/logo.svg +3 -3
  44. package/src/assets/styles/2026/_animations.scss +14 -0
  45. package/src/assets/styles/2026/_auth.scss +215 -0
  46. package/src/assets/styles/2026/_base.scss +37 -0
  47. package/src/assets/styles/2026/_calendar.scss +380 -0
  48. package/src/assets/styles/2026/_charts.scss +44 -0
  49. package/src/assets/styles/2026/_chat.scss +350 -0
  50. package/src/assets/styles/2026/_components.scss +140 -0
  51. package/src/assets/styles/2026/_dashboard.scss +520 -0
  52. package/src/assets/styles/2026/_data.scss +130 -0
  53. package/src/assets/styles/2026/_dropdowns.scss +128 -0
  54. package/src/assets/styles/2026/_email.scss +599 -0
  55. package/src/assets/styles/2026/_error.scss +98 -0
  56. package/src/assets/styles/2026/_forms.scss +215 -0
  57. package/src/assets/styles/2026/_fullcalendar.scss +134 -0
  58. package/src/assets/styles/2026/_palette.scss +173 -0
  59. package/src/assets/styles/2026/_responsive.scss +229 -0
  60. package/src/assets/styles/2026/_shell.scss +290 -0
  61. package/src/assets/styles/2026/_tokens.scss +80 -0
  62. package/src/assets/styles/2026/_ui.scss +365 -0
  63. package/src/assets/styles/2026/index.scss +23 -0
  64. package/src/basic-table.html +153 -710
  65. package/src/blank.html +42 -517
  66. package/src/buttons.html +152 -458
  67. package/src/calendar.html +246 -668
  68. package/src/charts.html +124 -668
  69. package/src/chat.html +209 -716
  70. package/src/compose.html +142 -629
  71. package/src/datatable.html +466 -1000
  72. package/src/email.html +429 -952
  73. package/src/forms.html +207 -742
  74. package/src/google-maps.html +128 -523
  75. package/src/index.html +438 -1050
  76. package/src/signin.html +92 -92
  77. package/src/signup.html +106 -91
  78. package/src/ui.html +267 -906
  79. package/src/vector-maps.html +133 -522
  80. package/dist/1e59d2330b4c6deb84b3.ttf +0 -0
  81. package/dist/20fd1704ea223900efa9.woff2 +0 -0
  82. package/dist/29b39089170885ae2967.woff +0 -0
  83. package/dist/8b43027f47b20503057d.eot +0 -0
  84. package/dist/9bad94440d49256265a5.eot +0 -0
  85. package/dist/assets/fontawesome-webfont.svg +0 -2671
  86. package/dist/assets/themify.svg +0 -362
  87. package/dist/eda8b94308c6f538f04a.ttf +0 -0
  88. package/dist/f691f37e57f04c152e23.woff +0 -0
  89. package/dist/main.js +0 -61323
  90. package/dist/main.js.map +0 -1
  91. package/src/assets/scripts/app 2.js +0 -645
  92. package/src/assets/scripts/app.js +0 -645
  93. package/src/assets/scripts/charts/chartJS/index.js +0 -148
  94. package/src/assets/scripts/charts/easyPieChart/index.js +0 -200
  95. package/src/assets/scripts/charts/index.js +0 -3
  96. package/src/assets/scripts/charts/sparkline/index.js +0 -208
  97. package/src/assets/scripts/chat/index.js +0 -11
  98. package/src/assets/scripts/components/Chart.js +0 -1390
  99. package/src/assets/scripts/components/Sidebar.js +0 -241
  100. package/src/assets/scripts/constants/colors.js +0 -274
  101. package/src/assets/scripts/datatable/index.js +0 -379
  102. package/src/assets/scripts/datepicker/index.js +0 -302
  103. package/src/assets/scripts/email/index.js +0 -25
  104. package/src/assets/scripts/fullcalendar/index.js +0 -86
  105. package/src/assets/scripts/googleMaps/index.js +0 -93
  106. package/src/assets/scripts/index.js +0 -18
  107. package/src/assets/scripts/masonry/index.js +0 -14
  108. package/src/assets/scripts/popover/index.js +0 -109
  109. package/src/assets/scripts/scrollbar/index.js +0 -10
  110. package/src/assets/scripts/search/index.js +0 -15
  111. package/src/assets/scripts/sidebar/index.js +0 -140
  112. package/src/assets/scripts/skycons/index.js +0 -52
  113. package/src/assets/scripts/ui/index.js +0 -412
  114. package/src/assets/scripts/utils/date.js +0 -242
  115. package/src/assets/scripts/utils/dom.js +0 -349
  116. package/src/assets/scripts/utils/index.js +0 -45
  117. package/src/assets/scripts/utils/theme.js +0 -107
  118. package/src/assets/scripts/vectorMaps/index.js +0 -277
  119. package/src/assets/styles/index.scss +0 -801
  120. package/src/assets/styles/spec/components/easyPieChart.scss +0 -11
  121. package/src/assets/styles/spec/components/footer.scss +0 -4
  122. package/src/assets/styles/spec/components/forms.scss +0 -288
  123. package/src/assets/styles/spec/components/index.scss +0 -9
  124. package/src/assets/styles/spec/components/loader.scss +0 -46
  125. package/src/assets/styles/spec/components/masonry.scss +0 -1
  126. package/src/assets/styles/spec/components/pageContainer.scss +0 -255
  127. package/src/assets/styles/spec/components/progressBar.scss +0 -6
  128. package/src/assets/styles/spec/components/sidebar.scss +0 -642
  129. package/src/assets/styles/spec/components/topbar.scss +0 -455
  130. package/src/assets/styles/spec/generic/base.scss +0 -102
  131. package/src/assets/styles/spec/generic/index.scss +0 -1
  132. package/src/assets/styles/spec/index.scss +0 -4
  133. package/src/assets/styles/spec/screens/chat.scss +0 -147
  134. package/src/assets/styles/spec/screens/email.scss +0 -108
  135. package/src/assets/styles/spec/screens/index.scss +0 -2
  136. package/src/assets/styles/spec/settings/baseColors.scss +0 -103
  137. package/src/assets/styles/spec/settings/borders.scss +0 -6
  138. package/src/assets/styles/spec/settings/breakpoints.scss +0 -26
  139. package/src/assets/styles/spec/settings/fonts.scss +0 -4
  140. package/src/assets/styles/spec/settings/index.scss +0 -4
  141. package/src/assets/styles/spec/settings/materialColors.scss +0 -550
  142. package/src/assets/styles/spec/tools/index.scss +0 -1
  143. package/src/assets/styles/spec/tools/mixins/clearfix.scss +0 -15
  144. package/src/assets/styles/spec/tools/mixins/index.scss +0 -3
  145. package/src/assets/styles/spec/tools/mixins/mediaQueriesRanges.scss +0 -58
  146. package/src/assets/styles/spec/tools/mixins/placeholder.scss +0 -10
  147. package/src/assets/styles/spec/utils/colors.scss +0 -33
  148. package/src/assets/styles/spec/utils/index.scss +0 -2
  149. package/src/assets/styles/spec/utils/layout/helpers/border.scss +0 -78
  150. package/src/assets/styles/spec/utils/layout/helpers/flex.scss +0 -220
  151. package/src/assets/styles/spec/utils/layout/helpers/index.scss +0 -11
  152. package/src/assets/styles/spec/utils/layout/helpers/layout.scss +0 -137
  153. package/src/assets/styles/spec/utils/layout/helpers/lists.scss +0 -23
  154. package/src/assets/styles/spec/utils/layout/helpers/margin.scss +0 -266
  155. package/src/assets/styles/spec/utils/layout/helpers/objects.scss +0 -91
  156. package/src/assets/styles/spec/utils/layout/helpers/padding.scss +0 -147
  157. package/src/assets/styles/spec/utils/layout/helpers/positions.scss +0 -118
  158. package/src/assets/styles/spec/utils/layout/helpers/pseudo.scss +0 -6
  159. package/src/assets/styles/spec/utils/layout/helpers/sizes.scss +0 -157
  160. package/src/assets/styles/spec/utils/layout/helpers/typography.scss +0 -127
  161. package/src/assets/styles/spec/utils/layout/index.scss +0 -3
  162. package/src/assets/styles/spec/utils/layout/mixins/generateResponsive.scss +0 -25
  163. package/src/assets/styles/spec/utils/layout/mixins/index.scss +0 -2
  164. package/src/assets/styles/spec/utils/layout/mixins/mediaQueryCondition.scss +0 -28
  165. package/src/assets/styles/spec/utils/layout/utils/center.scss +0 -54
  166. package/src/assets/styles/spec/utils/layout/utils/gap.scss +0 -229
  167. package/src/assets/styles/spec/utils/layout/utils/index.scss +0 -5
  168. package/src/assets/styles/spec/utils/layout/utils/layers.scss +0 -5
  169. package/src/assets/styles/spec/utils/layout/utils/peers.scss +0 -35
  170. package/src/assets/styles/utils/mobile.scss +0 -954
  171. package/src/assets/styles/utils/theme.css +0 -97
  172. package/src/assets/styles/vendor/datepicker.scss +0 -183
  173. package/src/assets/styles/vendor/font-awesome.css +0 -2337
  174. package/src/assets/styles/vendor/fullcalendar.scss +0 -217
  175. package/src/assets/styles/vendor/index.scss +0 -8
  176. package/src/assets/styles/vendor/jquery.datatables.scss +0 -162
  177. package/src/assets/styles/vendor/perfectScrollbar.scss +0 -4
  178. package/src/assets/styles/vendor/sparkline.scss +0 -6
  179. package/src/assets/styles/vendor/themify-icons.css +0 -1081
@@ -0,0 +1,78 @@
1
+ /**
2
+ * jsvectormap wiring for the 2026 design system.
3
+ *
4
+ * Pages declare a vector map as <div data-vmap></div>; this module fills it
5
+ * with a world map themed using the active CSS variables and re-renders on
6
+ * theme change.
7
+ */
8
+
9
+ import jsVectorMap from 'jsvectormap';
10
+ import 'jsvectormap/dist/maps/world.js';
11
+ import 'jsvectormap/dist/jsvectormap.css';
12
+
13
+ const MARKERS = [
14
+ { name: 'Riga', coords: [56.95, 24.10] },
15
+ { name: 'New York', coords: [40.71, -74.00] },
16
+ { name: 'San Francisco',coords: [37.77, -122.42] },
17
+ { name: 'London', coords: [51.50, -0.12] },
18
+ { name: 'Berlin', coords: [52.52, 13.40] },
19
+ { name: 'Tokyo', coords: [35.68, 139.69] },
20
+ { name: 'Sydney', coords: [-33.86, 151.21] },
21
+ { name: 'São Paulo', coords: [-23.55, -46.63] },
22
+ { name: 'Cape Town', coords: [-33.92, 18.42] },
23
+ { name: 'Dubai', coords: [25.27, 55.30] },
24
+ ];
25
+
26
+ const instances = new Map();
27
+
28
+ function tokens() {
29
+ const cs = getComputedStyle(document.documentElement);
30
+ return {
31
+ primary: cs.getPropertyValue('--primary').trim(),
32
+ purple: cs.getPropertyValue('--purple').trim(),
33
+ soft: cs.getPropertyValue('--bg-muted').trim(),
34
+ border: cs.getPropertyValue('--border').trim(),
35
+ text: cs.getPropertyValue('--t-base').trim(),
36
+ bg: cs.getPropertyValue('--bg-card').trim(),
37
+ };
38
+ }
39
+
40
+ function buildOne(host) {
41
+ // Destroy old instance if rebuilding
42
+ const prev = instances.get(host);
43
+ if (prev) {
44
+ try { prev.destroy(); } catch { /* swallow — host is about to be replaced */ }
45
+ host.innerHTML = '';
46
+ }
47
+ const t = tokens();
48
+ const map = new jsVectorMap({
49
+ selector: host,
50
+ map: 'world',
51
+ backgroundColor: 'transparent',
52
+ zoomOnScroll: false,
53
+ regionStyle: {
54
+ initial: { fill: t.soft, stroke: t.border, strokeWidth: 0.4, fillOpacity: 1 },
55
+ hover: { fill: t.primary, fillOpacity: 0.5 },
56
+ },
57
+ markers: MARKERS,
58
+ markerStyle: {
59
+ initial: { fill: t.primary, stroke: t.bg, strokeWidth: 2, r: 5 },
60
+ hover: { fill: t.purple, stroke: t.bg, strokeWidth: 2, r: 7 },
61
+ },
62
+ labels: { markers: { render: (m) => m.name } },
63
+ });
64
+ instances.set(host, map);
65
+ }
66
+
67
+ function buildAll() {
68
+ document.querySelectorAll('[data-vmap]').forEach(buildOne);
69
+ }
70
+
71
+ export function initVectorMaps() {
72
+ if (!document.querySelector('[data-vmap]')) return;
73
+ buildAll();
74
+ const observer = new MutationObserver((records) => {
75
+ if (records.some((r) => r.attributeName === 'data-theme')) buildAll();
76
+ });
77
+ observer.observe(document.documentElement, { attributes: true });
78
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Command palette (⌘K / Ctrl+K).
3
+ *
4
+ * Builds a searchable modal of every NAV item plus a few global actions
5
+ * (toggle theme, view docs/repo). Opens via:
6
+ * - Click on any [data-palette-open] element (the topbar .cmd button)
7
+ * - Cmd/Ctrl + K keyboard shortcut, anywhere on the page
8
+ * - "/" keypress when no input is focused
9
+ *
10
+ * Closes via:
11
+ * - Esc
12
+ * - Click outside the panel
13
+ * - Selecting a result (Enter or click)
14
+ *
15
+ * Keyboard navigation: ↑ / ↓ to move, Enter to select.
16
+ *
17
+ * The palette renders into <body> the first time it's opened, then re-uses
18
+ * that DOM node. All state is local to this module.
19
+ */
20
+
21
+ import { NAV } from './Shell.js';
22
+
23
+ const PANEL_HTML = `
24
+ <div class="palette-modal" role="dialog" aria-modal="true" aria-label="Command palette">
25
+ <div class="palette-input-row">
26
+ <svg viewBox="0 0 24 24" class="palette-icon" aria-hidden="true">
27
+ <circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" stroke-width="2"/>
28
+ <path d="m21 21-4.3-4.3" fill="none" stroke="currentColor" stroke-width="2"/>
29
+ </svg>
30
+ <input class="palette-input" type="text" placeholder="Search pages, actions…" autocomplete="off" spellcheck="false">
31
+ <kbd class="palette-esc">esc</kbd>
32
+ </div>
33
+ <div class="palette-results" role="listbox"></div>
34
+ <div class="palette-foot">
35
+ <span><kbd>↑</kbd><kbd>↓</kbd> navigate</span>
36
+ <span><kbd>↵</kbd> select</span>
37
+ <span><kbd>esc</kbd> close</span>
38
+ </div>
39
+ </div>
40
+ `;
41
+
42
+ let backdrop = null;
43
+ let modal = null;
44
+ let input = null;
45
+ let resultsEl = null;
46
+ let allItems = [];
47
+ let filtered = [];
48
+ let cursor = 0;
49
+
50
+ function buildItems() {
51
+ // Flatten the NAV manifest into a single list of selectable rows.
52
+ const items = [];
53
+
54
+ for (const section of NAV) {
55
+ for (const item of section.items) {
56
+ if (item.children) {
57
+ for (const child of item.children) {
58
+ items.push({
59
+ kind: 'page',
60
+ label: child.text,
61
+ section: `${section.label} › ${item.text}`,
62
+ href: child.href,
63
+ icon: item.icon,
64
+ });
65
+ }
66
+ } else if (item.href && item.href !== '#') {
67
+ items.push({
68
+ kind: 'page',
69
+ label: item.text,
70
+ section: section.label,
71
+ href: item.href,
72
+ icon: item.icon,
73
+ });
74
+ }
75
+ }
76
+ }
77
+
78
+ // Static actions
79
+ items.push({
80
+ kind: 'action',
81
+ label: 'Toggle theme (light / dark)',
82
+ section: 'Action',
83
+ action: () => {
84
+ const root = document.documentElement;
85
+ const next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
86
+ root.setAttribute('data-theme', next);
87
+ try { localStorage.setItem('dash26-theme', next); } catch { /* no localStorage */ }
88
+ // Update the toggle button icon if init.js wired one.
89
+ const toggle = document.getElementById('themeToggle');
90
+ if (toggle) toggle.click(); // no-op if already in the right state, or just nudge it
91
+ },
92
+ icon: '<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>',
93
+ });
94
+ items.push({
95
+ kind: 'link',
96
+ label: 'View on GitHub',
97
+ section: 'External',
98
+ href: 'https://github.com/puikinsh/Adminator-admin-dashboard',
99
+ target: '_blank',
100
+ icon: '<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/>',
101
+ });
102
+ items.push({
103
+ kind: 'link',
104
+ label: 'Documentation',
105
+ section: 'External',
106
+ href: 'https://puikinsh.github.io/Adminator-admin-dashboard/',
107
+ target: '_blank',
108
+ icon: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M16 13H8M16 17H8M10 9H8"/>',
109
+ });
110
+
111
+ return items;
112
+ }
113
+
114
+ function score(item, query) {
115
+ if (!query) return 1;
116
+ const q = query.toLowerCase();
117
+ const label = item.label.toLowerCase();
118
+ if (label === q) return 100;
119
+ if (label.startsWith(q)) return 50;
120
+ if (label.includes(q)) return 20;
121
+ if (item.section.toLowerCase().includes(q)) return 5;
122
+ return 0;
123
+ }
124
+
125
+ function renderResults() {
126
+ resultsEl.innerHTML = filtered.length === 0
127
+ ? '<div class="palette-empty">No results</div>'
128
+ : filtered.map((item, i) => `
129
+ <div class="palette-result${i === cursor ? ' is-selected' : ''}" role="option" data-index="${i}" aria-selected="${i === cursor}">
130
+ <span class="palette-result-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">${item.icon || ''}</svg></span>
131
+ <span class="palette-result-label">${item.label}</span>
132
+ <span class="palette-result-section">${item.section}</span>
133
+ </div>
134
+ `).join('');
135
+ }
136
+
137
+ function update(query) {
138
+ filtered = allItems
139
+ .map((item) => ({ item, s: score(item, query) }))
140
+ .filter((x) => x.s > 0)
141
+ .sort((a, b) => b.s - a.s)
142
+ .slice(0, 12)
143
+ .map((x) => x.item);
144
+ cursor = 0;
145
+ renderResults();
146
+ }
147
+
148
+ function activate(item) {
149
+ if (!item) return;
150
+ close();
151
+ if (item.kind === 'action' && typeof item.action === 'function') {
152
+ item.action();
153
+ } else if (item.href) {
154
+ if (item.target === '_blank') {
155
+ window.open(item.href, '_blank', 'noopener');
156
+ } else {
157
+ window.location.href = item.href;
158
+ }
159
+ }
160
+ }
161
+
162
+ function ensureMounted() {
163
+ // If the cached modal was removed from the DOM (e.g. by a test or by code
164
+ // that wipes <body>), drop the stale refs and remount.
165
+ if (modal && !document.contains(modal)) {
166
+ modal = null; backdrop = null; input = null; resultsEl = null;
167
+ }
168
+ if (modal) return;
169
+ backdrop = document.createElement('div');
170
+ backdrop.className = 'palette-backdrop';
171
+ backdrop.innerHTML = PANEL_HTML;
172
+ document.body.appendChild(backdrop);
173
+ modal = backdrop.querySelector('.palette-modal');
174
+ input = backdrop.querySelector('.palette-input');
175
+ resultsEl = backdrop.querySelector('.palette-results');
176
+
177
+ backdrop.addEventListener('click', (e) => {
178
+ if (e.target === backdrop) close();
179
+ });
180
+ input.addEventListener('input', () => update(input.value));
181
+ input.addEventListener('keydown', (e) => {
182
+ if (e.key === 'ArrowDown') {
183
+ e.preventDefault();
184
+ cursor = Math.min(cursor + 1, filtered.length - 1);
185
+ renderResults();
186
+ scrollCursorIntoView();
187
+ } else if (e.key === 'ArrowUp') {
188
+ e.preventDefault();
189
+ cursor = Math.max(cursor - 1, 0);
190
+ renderResults();
191
+ scrollCursorIntoView();
192
+ } else if (e.key === 'Enter') {
193
+ e.preventDefault();
194
+ activate(filtered[cursor]);
195
+ } else if (e.key === 'Escape') {
196
+ e.preventDefault();
197
+ close();
198
+ }
199
+ });
200
+ resultsEl.addEventListener('click', (e) => {
201
+ const row = e.target.closest('.palette-result');
202
+ if (row) activate(filtered[Number(row.getAttribute('data-index'))]);
203
+ });
204
+ }
205
+
206
+ function scrollCursorIntoView() {
207
+ const sel = resultsEl.querySelector('.palette-result.is-selected');
208
+ if (sel && typeof sel.scrollIntoView === 'function') {
209
+ sel.scrollIntoView({ block: 'nearest' });
210
+ }
211
+ }
212
+
213
+ export function open() {
214
+ ensureMounted();
215
+ if (allItems.length === 0) allItems = buildItems();
216
+ input.value = '';
217
+ update('');
218
+ document.body.classList.add('has-palette-open');
219
+ // Focus on next tick (jsdom-friendly).
220
+ setTimeout(() => input.focus(), 0);
221
+ }
222
+
223
+ export function close() {
224
+ if (!modal) return;
225
+ document.body.classList.remove('has-palette-open');
226
+ }
227
+
228
+ export function isOpen() {
229
+ return document.body.classList.contains('has-palette-open');
230
+ }
231
+
232
+ let _initialized = false;
233
+
234
+ export function initPalette() {
235
+ // Guard against being called twice (e.g. when init runs on both
236
+ // DOMContentLoaded and on a manual re-init after hot reload). Without
237
+ // this, every keydown handler runs N times, which causes Cmd+K to net-no-op
238
+ // on the second invocation.
239
+ if (_initialized) return;
240
+ _initialized = true;
241
+
242
+ document.addEventListener('click', (e) => {
243
+ if (e.target.closest('[data-palette-open]')) {
244
+ e.preventDefault();
245
+ open();
246
+ }
247
+ });
248
+
249
+ document.addEventListener('keydown', (e) => {
250
+ // Cmd+K (Mac) / Ctrl+K (Windows/Linux): open from anywhere
251
+ if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
252
+ e.preventDefault();
253
+ isOpen() ? close() : open();
254
+ return;
255
+ }
256
+ // Slash: open when no input is focused
257
+ if (e.key === '/' && !isOpen()) {
258
+ const tag = document.activeElement && document.activeElement.tagName;
259
+ const editable = document.activeElement && document.activeElement.isContentEditable;
260
+ if (tag !== 'INPUT' && tag !== 'TEXTAREA' && tag !== 'SELECT' && !editable) {
261
+ e.preventDefault();
262
+ open();
263
+ }
264
+ }
265
+ });
266
+ }
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <svg width="800px" height="800px" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="colorlib adminator" preserveAspectRatio="xMidYMid meet">
3
- <path fill="#3B88C3" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"/>
4
- <path fill="currentColor" d="M14.747 9.125c.527-1.426 1.736-2.573 3.317-2.573c1.643 0 2.792 1.085 3.318 2.573l6.077 16.867c.186.496.248.931.248 1.147c0 1.209-.992 2.046-2.139 2.046c-1.303 0-1.954-.682-2.264-1.611l-.931-2.915h-8.62l-.93 2.884c-.31.961-.961 1.642-2.232 1.642c-1.24 0-2.294-.93-2.294-2.17c0-.496.155-.868.217-1.023l6.233-16.867zm.34 11.256h5.891l-2.883-8.992h-.062l-2.946 8.992z"/>
5
- </svg>
3
+ <path fill="#6366f1" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"/>
4
+ <path fill="#ffffff" d="M14.747 9.125c.527-1.426 1.736-2.573 3.317-2.573c1.643 0 2.792 1.085 3.318 2.573l6.077 16.867c.186.496.248.931.248 1.147c0 1.209-.992 2.046-2.139 2.046c-1.303 0-1.954-.682-2.264-1.611l-.931-2.915h-8.62l-.93 2.884c-.31.961-.961 1.642-2.232 1.642c-1.24 0-2.294-.93-2.294-2.17c0-.496.155-.868.217-1.023l6.233-16.867zm.34 11.256h5.891l-2.883-8.992h-.062l-2.946 8.992z"/>
5
+ </svg>
@@ -0,0 +1,14 @@
1
+ /* ============ ANIMATIONS — 2026 ============ */
2
+
3
+ @keyframes rise-in {
4
+ from { opacity: 0; transform: translateY(10px); }
5
+ to { opacity: 1; transform: translateY(0); }
6
+ }
7
+
8
+ @keyframes bar-in {
9
+ from { transform: scaleX(0); }
10
+ to { transform: scaleX(1); }
11
+ }
12
+
13
+ @keyframes draw { to { stroke-dashoffset: 0; } }
14
+ @keyframes fade-in { to { opacity: 1; } }
@@ -0,0 +1,215 @@
1
+ /* ============ AUTH PAGES ============ */
2
+
3
+ .auth-shell {
4
+ display: grid;
5
+ grid-template-columns: 1fr 1fr;
6
+ min-height: 100vh;
7
+ background: var(--bg-body);
8
+ }
9
+
10
+ /* Responsive override for .auth-aside lives in _responsive.scss to win over
11
+ the default rules below — see chat note for why. */
12
+
13
+ .auth-aside {
14
+ position: relative;
15
+ background: linear-gradient(135deg, var(--primary), var(--purple));
16
+ color: #fff;
17
+ padding: 40px 48px;
18
+ display: flex; flex-direction: column;
19
+ overflow: hidden;
20
+ }
21
+ .auth-aside::before {
22
+ content: '';
23
+ position: absolute;
24
+ inset: -40% -20% auto auto;
25
+ width: 80%; aspect-ratio: 1;
26
+ background: radial-gradient(circle, rgba(255,255,255,.18), transparent 60%);
27
+ pointer-events: none;
28
+ }
29
+ .auth-aside::after {
30
+ content: '';
31
+ position: absolute;
32
+ inset: auto auto -30% -20%;
33
+ width: 80%; aspect-ratio: 1;
34
+ background: radial-gradient(circle, rgba(255,255,255,.10), transparent 60%);
35
+ pointer-events: none;
36
+ }
37
+
38
+ .auth-brand {
39
+ display: flex; align-items: center; gap: 10px;
40
+ position: relative; z-index: 1;
41
+ }
42
+ .auth-brand .logo {
43
+ width: 36px; height: 36px;
44
+ background: rgba(255,255,255,0.18);
45
+ border: 1px solid rgba(255,255,255,0.25);
46
+ backdrop-filter: blur(6px);
47
+ border-radius: 9px;
48
+ display: grid; place-items: center;
49
+ }
50
+ .auth-brand .logo svg { width: 20px; height: 20px; }
51
+ .auth-brand .name {
52
+ font-family: 'Inter Tight', sans-serif;
53
+ font-weight: 700;
54
+ font-size: 16px;
55
+ letter-spacing: -0.018em;
56
+ }
57
+
58
+ .auth-aside-body {
59
+ margin-top: auto;
60
+ position: relative; z-index: 1;
61
+ max-width: 440px;
62
+ }
63
+ .auth-aside-eyebrow {
64
+ font-family: 'JetBrains Mono', monospace;
65
+ font-size: 10px;
66
+ letter-spacing: 0.18em;
67
+ text-transform: uppercase;
68
+ color: rgba(255,255,255,.7);
69
+ margin-bottom: 14px;
70
+ display: block;
71
+ }
72
+ .auth-aside h1 {
73
+ font-family: 'Inter Tight', sans-serif;
74
+ font-weight: 700;
75
+ font-size: clamp(28px, 3vw, 38px);
76
+ letter-spacing: -0.025em;
77
+ line-height: 1.15;
78
+ margin: 0 0 14px;
79
+ }
80
+ .auth-aside p {
81
+ font-size: 14.5px;
82
+ color: rgba(255,255,255,.85);
83
+ line-height: 1.6;
84
+ margin: 0 0 24px;
85
+ }
86
+
87
+ .auth-quote {
88
+ margin-top: 32px;
89
+ padding: 18px 20px;
90
+ border: 1px solid rgba(255,255,255,0.18);
91
+ background: rgba(255,255,255,0.08);
92
+ backdrop-filter: blur(6px);
93
+ border-radius: 12px;
94
+ font-size: 13px;
95
+ color: rgba(255,255,255,.9);
96
+ line-height: 1.6;
97
+ }
98
+ .auth-quote-author {
99
+ display: flex; align-items: center; gap: 10px;
100
+ margin-top: 14px;
101
+ font-size: 12px;
102
+ color: rgba(255,255,255,.75);
103
+ }
104
+ .auth-quote-author .av {
105
+ width: 28px; height: 28px;
106
+ border-radius: 50%;
107
+ background: rgba(255,255,255,0.22);
108
+ display: grid; place-items: center;
109
+ font-size: 11px; font-weight: 600;
110
+ }
111
+
112
+ .auth-aside-footer {
113
+ margin-top: auto;
114
+ padding-top: 24px;
115
+ position: relative; z-index: 1;
116
+ display: flex; gap: 18px;
117
+ font-family: 'JetBrains Mono', monospace;
118
+ font-size: 10px;
119
+ color: rgba(255,255,255,.55);
120
+ letter-spacing: 0.06em;
121
+ }
122
+
123
+ .auth-main {
124
+ display: flex; flex-direction: column;
125
+ padding: 32px 48px;
126
+ min-height: 100vh;
127
+ }
128
+
129
+ .auth-main-top {
130
+ display: flex; justify-content: space-between; align-items: center;
131
+ }
132
+ .auth-main-top .switch-link {
133
+ font-size: 12.5px;
134
+ color: var(--t-muted);
135
+ }
136
+ .auth-main-top .switch-link a {
137
+ color: var(--primary);
138
+ font-weight: 600;
139
+ margin-left: 4px;
140
+ }
141
+
142
+ .auth-card {
143
+ width: 100%;
144
+ max-width: 400px;
145
+ margin: auto;
146
+ padding: 8px 0;
147
+ }
148
+ .auth-card h2 {
149
+ font-family: 'Inter Tight', sans-serif;
150
+ font-weight: 700;
151
+ font-size: 26px;
152
+ letter-spacing: -0.022em;
153
+ color: var(--t-base);
154
+ margin: 0 0 6px;
155
+ }
156
+ .auth-card .sub {
157
+ font-size: 13.5px;
158
+ color: var(--t-muted);
159
+ margin: 0 0 24px;
160
+ line-height: 1.55;
161
+ }
162
+
163
+ .auth-form { display: flex; flex-direction: column; gap: 14px; }
164
+ .auth-form .field-row {
165
+ display: flex; justify-content: space-between; align-items: center;
166
+ }
167
+ .auth-form .field-row a {
168
+ color: var(--primary);
169
+ font-size: 12px;
170
+ font-weight: 600;
171
+ }
172
+ .auth-submit { margin-top: 4px; }
173
+ .auth-submit.btn { padding: 11px 14px; }
174
+
175
+ .auth-divider {
176
+ display: flex; align-items: center; gap: 12px;
177
+ font-family: 'JetBrains Mono', monospace;
178
+ font-size: 10px;
179
+ color: var(--t-light);
180
+ letter-spacing: 0.14em;
181
+ text-transform: uppercase;
182
+ margin: 18px 0;
183
+ }
184
+ .auth-divider::before,
185
+ .auth-divider::after {
186
+ content: '';
187
+ flex: 1;
188
+ height: 1px;
189
+ background: var(--border);
190
+ }
191
+
192
+ .social-row {
193
+ display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
194
+ }
195
+ .social-btn {
196
+ display: inline-flex; align-items: center; justify-content: center; gap: 8px;
197
+ padding: 9px 12px;
198
+ border: 1px solid var(--border);
199
+ border-radius: 8px;
200
+ background: var(--bg-card);
201
+ color: var(--t-base);
202
+ font-size: 12.5px;
203
+ font-weight: 600;
204
+ transition: border-color 160ms, box-shadow 160ms, background 160ms;
205
+ }
206
+ .social-btn:hover { border-color: var(--t-light); box-shadow: var(--shadow-sm); }
207
+ .social-btn svg { width: 14px; height: 14px; }
208
+
209
+ .auth-main-bottom {
210
+ margin-top: 24px;
211
+ font-size: 11.5px;
212
+ color: var(--t-light);
213
+ text-align: center;
214
+ }
215
+ .auth-main-bottom a { color: var(--t-muted); }
@@ -0,0 +1,37 @@
1
+ /* ============ RESET + BASE — 2026 ============ */
2
+
3
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Inter+Tight:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
4
+
5
+ *, *::before, *::after { box-sizing: border-box; }
6
+ html, body { margin: 0; padding: 0; }
7
+ a { color: inherit; text-decoration: none; }
8
+ button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }
9
+ ul, ol { margin: 0; padding: 0; list-style: none; }
10
+ img, svg { display: block; max-width: 100%; }
11
+ input, textarea { font: inherit; color: inherit; }
12
+
13
+ body {
14
+ font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
15
+ font-feature-settings: 'cv11', 'ss01', 'ss03';
16
+ font-weight: 400;
17
+ background: var(--bg-body);
18
+ color: var(--t-base);
19
+ font-size: 14px;
20
+ line-height: 1.55;
21
+ letter-spacing: -0.003em;
22
+ -webkit-font-smoothing: antialiased;
23
+ text-rendering: optimizeLegibility;
24
+ transition: background-color 280ms ease, color 280ms ease;
25
+ }
26
+ ::selection { background: var(--primary); color: #fff; }
27
+
28
+ .mono { font-family: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', monospace; }
29
+
30
+ .eyebrow {
31
+ font-family: 'JetBrains Mono', monospace;
32
+ font-size: 10px;
33
+ letter-spacing: 0.18em;
34
+ text-transform: uppercase;
35
+ color: var(--t-light);
36
+ font-weight: 500;
37
+ }