claude-memory-admin 1.5.1 → 1.6.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.
Files changed (39) hide show
  1. package/README.md +79 -124
  2. package/package.json +1 -1
  3. package/public/api.mjs +26 -0
  4. package/public/app.mjs +35 -2270
  5. package/public/bus.mjs +7 -0
  6. package/public/dialog.mjs +7 -0
  7. package/public/dialogs/add-entry.mjs +69 -0
  8. package/public/dialogs/bulk-delete.mjs +59 -0
  9. package/public/dialogs/delete.mjs +114 -0
  10. package/public/dialogs/hook-editor.mjs +54 -0
  11. package/public/dialogs/merge.mjs +81 -0
  12. package/public/dialogs/move.mjs +43 -0
  13. package/public/dialogs/remember-path.mjs +65 -0
  14. package/public/dialogs/store-delete.mjs +64 -0
  15. package/public/dialogs/trash.mjs +53 -0
  16. package/public/index.html +1 -0
  17. package/public/parts.mjs +65 -0
  18. package/public/state.mjs +48 -0
  19. package/public/store.mjs +121 -0
  20. package/public/styles.css +1 -1
  21. package/public/ui.mjs +44 -16
  22. package/public/views/cleanup.mjs +63 -0
  23. package/public/views/context.mjs +121 -0
  24. package/public/views/cost-issue.mjs +70 -0
  25. package/public/views/environment.mjs +12 -0
  26. package/public/views/header.mjs +183 -0
  27. package/public/views/index.mjs +122 -0
  28. package/public/views/issue.mjs +262 -0
  29. package/public/views/memories.mjs +156 -0
  30. package/public/views/memory-list.mjs +121 -0
  31. package/public/views/memory.mjs +32 -0
  32. package/public/views/path-check.mjs +103 -0
  33. package/public/views/search.mjs +100 -0
  34. package/public/views/segments.mjs +37 -0
  35. package/public/views/sessions.mjs +235 -0
  36. package/public/views/settings.mjs +121 -0
  37. package/public/views/stores.mjs +65 -0
  38. package/public/views/worklist.mjs +33 -0
  39. package/src/sessions.mjs +69 -1
@@ -0,0 +1,65 @@
1
+ import * as ui from '/ui.mjs';
2
+ import { node } from '/dom.mjs';
3
+ import { state, SEGMENT_STORAGE } from '/state.mjs';
4
+ import { paint } from '/bus.mjs';
5
+
6
+ export function issue(title, detail, { bad = false, action, secondary } = {}) {
7
+ return node('div', { class: ui.issue(bad) }, [
8
+ node('div', { class: ui.issueBody }, [
9
+ node('div', { class: ui.issueTitle, text: title }),
10
+ node('div', { class: ui.issueDetail, text: detail }),
11
+ ]),
12
+ secondary ? node('button', { class: ui.buttonSmall, text: secondary.label, onclick: secondary.run }) : null,
13
+ action ? node('button', { class: ui.buttonSmall, text: action.label, onclick: action.run }) : null,
14
+ ]);
15
+ }
16
+
17
+ export function goTo(tab, segment) {
18
+ state.tab = tab;
19
+ if (segment && SEGMENT_STORAGE[tab]) {
20
+ state.segment[tab] = segment;
21
+ localStorage.setItem(SEGMENT_STORAGE[tab], segment);
22
+ }
23
+ paint('tabs', 'tab');
24
+ }
25
+
26
+ export const isAt = (tab, segment) => state.tab === tab
27
+ && (!segment || state.segment[tab] === segment);
28
+
29
+ export function cutMarker(cutoff) {
30
+ return node('div', { class: ui.cutLine }, [
31
+ node('span', { class: ui.cutLabel, text: `not loaded past here — ${cutoff.droppedLines} lines dropped on ${cutoff.by}` }),
32
+ ]);
33
+ }
34
+
35
+ export function highlight(text, terms) {
36
+ const wrapper = node('span');
37
+ if (!terms.length) { wrapper.textContent = text; return wrapper; }
38
+ const pattern = new RegExp(`(${terms.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')})`, 'ig');
39
+ let last = 0;
40
+ for (const match of text.matchAll(pattern)) {
41
+ if (match.index > last) wrapper.append(document.createTextNode(text.slice(last, match.index)));
42
+ wrapper.append(node('mark', { class: ui.resultMark, text: match[0] }));
43
+ last = match.index + match[0].length;
44
+ }
45
+ if (last < text.length) wrapper.append(document.createTextNode(text.slice(last)));
46
+ return wrapper;
47
+ }
48
+
49
+ export function formatAge(days) {
50
+ if (days === null || days === undefined) return 'undated';
51
+ if (days < 1) return 'today';
52
+ if (days < 31) return `${days}d`;
53
+ if (days < 365) return `${Math.round(days / 30)}mo`;
54
+ return `${(days / 365).toFixed(1)}y`;
55
+ }
56
+
57
+ export const sizeLabel = (bytes) => (bytes >= 1048576
58
+ ? `${(bytes / 1048576).toFixed(1)} MB`
59
+ : `${(bytes / 1024).toFixed(1)} KB`);
60
+
61
+ export function sessionDate(iso) {
62
+ return iso ? iso.replace('T', ' ').replace(/\..*$/, '') : 'unknown';
63
+ }
64
+
65
+ export const byteLength = (text) => new TextEncoder().encode(text).length;
@@ -0,0 +1,48 @@
1
+ export const SEGMENT_STORAGE = {
2
+ memory: 'navMemorySegment',
3
+ environment: 'navEnvironmentSegment',
4
+ };
5
+
6
+ const SEGMENTS = {
7
+ memory: ['list', 'index', 'graph'],
8
+ environment: ['instructions', 'settings', 'sessions'],
9
+ };
10
+
11
+ const storedSegment = (tab) => {
12
+ const value = localStorage.getItem(SEGMENT_STORAGE[tab]);
13
+ return SEGMENTS[tab].includes(value) ? value : SEGMENTS[tab][0];
14
+ };
15
+
16
+ const LIST_SORTS = ['section', 'oldest', 'largest', 'unlinked', 'name'];
17
+ const storedListSort = () => {
18
+ const value = localStorage.getItem('memoryListSort');
19
+ return LIST_SORTS.includes(value) ? value : 'section';
20
+ };
21
+
22
+ export const state = {
23
+ stores: [],
24
+ storeId: null,
25
+ store: null,
26
+ tab: 'memory',
27
+ segment: {
28
+ memory: storedSegment('memory'),
29
+ environment: storedSegment('environment'),
30
+ },
31
+ selected: null,
32
+ showAll: false,
33
+ collapsed: localStorage.getItem('sidebarCollapsed') === '1',
34
+ theme: document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light',
35
+ spread: Number(localStorage.getItem('graphSpread')) || 1.6,
36
+ query: '',
37
+ search: null,
38
+ listSort: storedListSort(),
39
+ listSelection: new Set(),
40
+ selecting: false,
41
+ indexView: localStorage.getItem('memoryIndexView') === 'source' ? 'source' : 'rendered',
42
+ aux: { instructions: null, settings: null, sessions: null, sessionDay: null },
43
+ pathCheck: null,
44
+ };
45
+
46
+ const RANK = { ok: 0, warn: 1, bad: 2 };
47
+ export const worst = (...severities) => severities.reduce((a, b) => (RANK[b] > RANK[a] ? b : a), 'ok');
48
+ export const worstSeverity = (items) => (!items.length ? 'ok' : items.some((item) => item.severity === 'bad') ? 'bad' : 'warn');
@@ -0,0 +1,121 @@
1
+ import { api, toast } from '/api.mjs';
2
+ import { state, worst, worstSeverity } from '/state.mjs';
3
+ import { paint } from '/bus.mjs';
4
+ import { closeDialog } from '/dialog.mjs';
5
+ import { goTo } from '/parts.mjs';
6
+
7
+ export async function openStore(id, { keepTab = false } = {}) {
8
+ if (id !== state.storeId) {
9
+ state.listSelection.clear();
10
+ state.selecting = false;
11
+ }
12
+ state.storeId = id;
13
+ state.aux = { instructions: null, settings: null, sessions: null, sessionDay: null };
14
+ state.pathCheck = null;
15
+ if (!keepTab) {
16
+ const opening = state.stores.find((store) => store.id === id);
17
+ state.tab = opening && opening.kind === 'global' ? 'environment' : 'memory';
18
+ state.selected = null;
19
+ }
20
+ paint('stores');
21
+
22
+ try {
23
+ state.store = await api(`/api/stores/${encodeURIComponent(id)}`);
24
+ } catch (err) {
25
+ return toast(err.message, { error: true });
26
+ }
27
+
28
+ if (state.selected && !state.store.memories.some((m) => m.file === state.selected)) {
29
+ state.selected = null;
30
+ }
31
+
32
+ paint('header');
33
+
34
+ const listed = state.stores.find((store) => store.id === id);
35
+ if (listed) {
36
+ listed.memoryCount = state.store.memories.length;
37
+ listed.issueCount = state.store.health.issueCount;
38
+ listed.severity = worst(state.store.health.severity, listed.context ? 'warn' : 'ok', listed.settings ? 'warn' : 'ok');
39
+ }
40
+ paint('stores');
41
+
42
+ paint('view');
43
+ paint('tabs', 'tab');
44
+
45
+ Promise.all([
46
+ api(`/api/stores/${encodeURIComponent(id)}/instructions`).catch(() => null),
47
+ api(`/api/stores/${encodeURIComponent(id)}/settings`).catch(() => null),
48
+ ]).then(([instructions, settings]) => {
49
+ if (state.storeId !== id) return;
50
+ state.aux = { ...state.aux, instructions, settings };
51
+ paint('tabs');
52
+ if (!listed) return;
53
+ listed.context = instructions ? instructions.problems.length : 0;
54
+ listed.settings = settings ? settings.problems.length : 0;
55
+ listed.severity = worst(
56
+ state.store.health.severity,
57
+ instructions ? worstSeverity(instructions.problems) : 'ok',
58
+ settings ? worstSeverity(settings.problems) : 'ok',
59
+ );
60
+ paint('stores');
61
+ });
62
+ }
63
+
64
+ export async function reloadStores() {
65
+ const data = await api('/api/stores');
66
+ state.stores = data.stores;
67
+ paint('stores');
68
+ sweepIssues();
69
+ return data;
70
+ }
71
+
72
+ export async function sweepIssues() {
73
+ let data;
74
+ try {
75
+ data = await api('/api/stores/issues');
76
+ } catch {
77
+ return;
78
+ }
79
+ const bySummary = new Map(data.stores.map((summary) => [summary.id, summary]));
80
+ for (const store of state.stores) Object.assign(store, bySummary.get(store.id) || {});
81
+ paint('stores');
82
+ }
83
+
84
+ export function selectMemory(file) {
85
+ state.selected = file;
86
+ if (state.tab !== 'memory' || state.segment.memory !== 'list') {
87
+ goTo('memory', 'list');
88
+ } else {
89
+ paint('tab');
90
+ }
91
+ document.querySelector('[data-memory][data-active]')?.scrollIntoView({ block: 'nearest' });
92
+ }
93
+
94
+ export async function loadSessionsForProvenance() {
95
+ if (state.aux.sessions || !state.store?.sessions?.count) return;
96
+ const id = state.storeId;
97
+ try {
98
+ const data = await api(`/api/stores/${encodeURIComponent(id)}/sessions`);
99
+ if (state.storeId !== id) return;
100
+ state.aux.sessions = data;
101
+ paint('tab');
102
+ } catch {
103
+ return;
104
+ }
105
+ }
106
+
107
+ export async function restoreFromTrash(id, { close = false } = {}) {
108
+ if (close) closeDialog();
109
+ try {
110
+ const result = await api(`/api/stores/${encodeURIComponent(state.storeId)}/restore`, {
111
+ method: 'POST',
112
+ body: JSON.stringify({ id }),
113
+ });
114
+ await openStore(state.storeId, { keepTab: true });
115
+ toast(result.indexRestored === 'appended'
116
+ ? 'Restored, but MEMORY.md had changed - the index line was appended at the end'
117
+ : 'Restored');
118
+ } catch (err) {
119
+ toast(err.message, { error: true });
120
+ }
121
+ }
package/public/styles.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-content:"";--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;--font-mono:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;--color-red-50:oklch(97.1% .013 17.4);--color-red-300:oklch(80.8% .114 19.6);--color-red-400:oklch(70.4% .16 22.2);--color-red-500:oklch(63.7% .208 25.3);--color-red-600:oklch(57.7% .215 27.3);--color-red-950:oklch(25.8% .092 26);--color-amber-50:oklch(97.7% .021 84.6);--color-amber-300:oklch(87.9% .153 91.6);--color-amber-400:oklch(82.8% .171 84.4);--color-amber-600:oklch(66.6% .15 58.3);--color-amber-700:oklch(55.5% .13 49);--color-amber-950:oklch(27.9% .077 45.6);--color-green-50:oklch(98.2% .018 155.8);--color-green-300:oklch(87.1% .12 154.4);--color-green-400:oklch(79.2% .15 151.7);--color-green-600:oklch(58.5% .145 149.2);--color-green-700:oklch(52.7% .132 150.1);--color-green-950:oklch(26.6% .065 152.9);--color-blue-50:oklch(97% .014 253.3);--color-blue-200:oklch(88% .06 253.3);--color-blue-300:oklch(78.4% .124 239.1);--color-blue-400:oklch(75.2% .138 243.7);--color-blue-600:oklch(56.5% .163 253.3);--color-blue-700:oklch(48.5% .15 253.3);--color-blue-800:oklch(41% .125 253.3);--color-blue-950:oklch(24% .07 253.3);--color-violet-50:oklch(96.9% .016 300);--color-violet-300:oklch(82.7% .104 300);--color-violet-700:oklch(49.6% .19 300);--color-violet-950:oklch(28.3% .109 300);--color-slate-50:oklch(98.4% .003 253.3);--color-slate-100:oklch(96.4% .005 253.3);--color-slate-200:oklch(92.6% .009 253.3);--color-slate-300:oklch(86.6% .014 253.3);--color-slate-400:oklch(70.4% .021 253.3);--color-slate-500:oklch(55.6% .026 253.3);--color-slate-600:oklch(44.8% .028 253.3);--color-slate-700:oklch(36.8% .028 253.3);--color-slate-800:oklch(26.4% .026 253.3);--color-slate-900:oklch(20.4% .024 253.3);--color-slate-950:oklch(14.2% .022 253.3);--spacing:.25rem;--container-2xl:42rem;--text-xs:.6875rem;--text-xs--line-height:1.45;--text-sm:.8125rem;--text-sm--line-height:1.5;--text-base:.875rem;--text-base--line-height:1.6;--text-lg:1rem;--text-lg--line-height:1.5;--text-xl:1.25rem;--text-xl--line-height:1.3;--text-2xl:1.5rem;--text-2xl--line-height:1.2;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-widest:.12em;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.12s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-slate-0:oklch(100% 0 253.3);--spacing-control-x-sm:calc(var(--spacing) * 2);--spacing-control-y-sm:calc(var(--spacing) * 1);--spacing-control-x-md:calc(var(--spacing) * 3);--spacing-control-y-md:calc(var(--spacing) * 2);--spacing-control-x-lg:calc(var(--spacing) * 3.5);--spacing-control-y-lg:calc(var(--spacing) * 2.5);--spacing-control-h-sm:calc(var(--spacing) * 6.5);--spacing-control-h-md:calc(var(--spacing) * 9.5);--spacing-control-h-lg:calc(var(--spacing) * 9.5);--text-2xs:.625rem;--text-2xs--line-height:1.4;--tracking-tightest:-.03em}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{color-scheme:light}:root[data-theme=dark]{color-scheme:dark}html,body{height:100%}body{background-color:var(--ui-canvas);color:var(--ui-fg);font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--text-base--line-height)}::selection{background-color:var(--ui-accent-surface);color:var(--ui-accent)}:focus-visible{outline:2px solid var(--ui-accent);outline-offset:1px}}@layer components{.prose{overflow-wrap:anywhere}.prose>:first-child{margin-top:0}.prose>:last-child{margin-bottom:0}.prose h1,.prose h2,.prose h3,.prose h4{margin:calc(var(--spacing) * 6) 0 calc(var(--spacing) * 2);letter-spacing:var(--tracking-tightest);font-weight:650;line-height:1.25}.prose h1{font-size:var(--text-lg)}.prose h2{font-size:var(--text-base);padding-bottom:calc(var(--spacing) * 1.5);border-bottom:1px solid var(--ui-line)}.prose h3,.prose h4{font-size:var(--text-base);color:var(--ui-fg-muted)}.prose p{margin:calc(var(--spacing) * 3) 0}.prose ul,.prose ol{margin:calc(var(--spacing) * 3) 0;padding-left:calc(var(--spacing) * 5)}.prose ul{list-style-type:"– "}.prose ol{list-style-type:decimal}.prose li{margin:calc(var(--spacing) * 1) 0}.prose li::marker{color:var(--ui-accent);font-family:var(--font-mono)}.prose li>ul,.prose li>ol{margin:calc(var(--spacing) * 1) 0}.prose a{color:var(--ui-accent);text-underline-offset:2px;text-decoration:underline}.prose a:hover{color:var(--ui-accent-hover)}.prose strong{color:var(--ui-fg);font-weight:650}.prose pre{margin:calc(var(--spacing) * 3) 0;padding:calc(var(--spacing) * 3);border:1px solid var(--ui-line);border-radius:var(--radius-md);background-color:var(--ui-surface-sunken);font-size:var(--text-xs);line-height:1.6;overflow-x:auto}.prose code{font-family:var(--font-mono);font-size:.9em}.prose :not(pre)>code{border:1px solid var(--ui-line);border-radius:var(--radius-sm);background-color:var(--ui-surface-sunken);color:var(--ui-accent);padding:1px 4px}.prose blockquote{margin:calc(var(--spacing) * 3) 0;padding-left:calc(var(--spacing) * 3);border-left:2px solid var(--ui-accent-line);color:var(--ui-fg-muted)}.prose hr{margin:calc(var(--spacing) * 5) 0;border:0;border-top:1px dashed var(--ui-line-strong)}.prose table{margin:calc(var(--spacing) * 3) 0;border-collapse:collapse;font-size:var(--text-sm);display:block;overflow-x:auto}.prose th,.prose td{padding:calc(var(--spacing) * 1.5) calc(var(--spacing) * 2.5);border:1px solid var(--ui-line);text-align:left}.prose th{background-color:var(--ui-surface-sunken);font-weight:600}.graph svg{cursor:grab;width:100%;display:block}.graph .node circle{cursor:pointer;stroke-width:1.5px}.graph .node circle.hit{fill:#0000;stroke:none}.graph .node text{fill:var(--ui-fg-muted);font-family:var(--font-mono);pointer-events:none;font-size:9px}.graph .node.hi circle{stroke:var(--ui-accent);stroke-width:2.5px}.graph .node.hi text{fill:var(--ui-fg);font-weight:600}.graph .node.dim{opacity:.18}.graph .node.dim text{display:none}.graph .edge{stroke:var(--ui-line-strong)}.graph .edge.dim{opacity:.05}}@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-y-0{inset-block:0}.top-0{top:0}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.top-3\.5{top:calc(var(--spacing) * 3.5)}.right-3\.5{right:calc(var(--spacing) * 3.5)}.bottom-2{bottom:calc(var(--spacing) * 2)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-5{bottom:calc(var(--spacing) * 5)}.left-0{left:0}.left-1\/2{left:50%}.left-3\.5{left:calc(var(--spacing) * 3.5)}.z-10{z-index:10}.z-20{z-index:20}.z-200{z-index:200}.float-right{float:right}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.m-auto{margin:auto}.my-1{margin-block:var(--spacing)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-0{margin-top:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.-mb-px{margin-bottom:-1px}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-3\.5{margin-bottom:calc(var(--spacing) * 3.5)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.h-2{height:calc(var(--spacing) * 2)}.h-9{height:calc(var(--spacing) * 9)}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[28rem\]{max-height:28rem}.max-h-\[82vh\]{max-height:82vh}.min-h-20{min-height:calc(var(--spacing) * 20)}.min-h-control-h-lg{min-height:var(--spacing-control-h-lg)}.min-h-control-h-md{min-height:var(--spacing-control-h-md)}.min-h-control-h-sm{min-height:var(--spacing-control-h-sm)}.w-0\.5{width:calc(var(--spacing) * .5)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-\[calc\(100\%-3rem\)\]{width:calc(100% - 3rem)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.min-w-0{min-width:0}.min-w-6{min-width:calc(var(--spacing) * 6)}.min-w-control-h-sm{min-width:var(--spacing-control-h-sm)}.flex-1{flex:1}.flex-none{flex:none}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[3rem_1fr\]{grid-template-columns:3rem 1fr}.grid-cols-\[280px_1fr\]{grid-template-columns:280px 1fr}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-px{gap:1px}.gap-x-3\.5{column-gap:calc(var(--spacing) * 3.5)}.gap-y-1{row-gap:var(--spacing)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-accent{border-color:var(--ui-accent)}.border-accent-line{border-color:var(--ui-accent-line)}.border-current{border-color:currentColor}.border-danger{border-color:var(--ui-danger)}.border-danger-line{border-color:var(--ui-danger-line)}.border-line{border-color:var(--ui-line)}.border-transparent{border-color:#0000}.border-l-danger{border-left-color:var(--ui-danger)}.border-l-warn{border-left-color:var(--ui-warn)}.bg-accent{background-color:var(--ui-accent)}.bg-accent-surface{background-color:var(--ui-accent-surface)}.bg-canvas{background-color:var(--ui-canvas)}.bg-danger{background-color:var(--ui-danger)}.bg-danger-surface{background-color:var(--ui-danger-surface)}.bg-fg{background-color:var(--ui-fg)}.bg-line-strong{background-color:var(--ui-line-strong)}.bg-ok{background-color:var(--ui-ok)}.bg-ok-surface{background-color:var(--ui-ok-surface)}.bg-scope-local-surface{background-color:var(--ui-scope-local-surface)}.bg-scope-managed-surface{background-color:var(--ui-scope-managed-surface)}.bg-scope-project-surface{background-color:var(--ui-scope-project-surface)}.bg-scope-user-surface{background-color:var(--ui-scope-user-surface)}.bg-surface{background-color:var(--ui-surface)}.bg-surface-sunken{background-color:var(--ui-surface-sunken)}.bg-transparent{background-color:#0000}.bg-type-feedback-surface{background-color:var(--ui-type-feedback-surface)}.bg-type-project-surface{background-color:var(--ui-type-project-surface)}.bg-type-reference-surface{background-color:var(--ui-type-reference-surface)}.bg-type-user-surface{background-color:var(--ui-type-user-surface)}.bg-warn{background-color:var(--ui-warn)}.bg-warn-surface{background-color:var(--ui-warn-surface)}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-10{padding:calc(var(--spacing) * 10)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.px-control-x-lg{padding-inline:var(--spacing-control-x-lg)}.px-control-x-md{padding-inline:var(--spacing-control-x-md)}.px-control-x-sm{padding-inline:var(--spacing-control-x-sm)}.px-px{padding-inline:1px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-\[15vh\]{padding-block:15vh}.py-control-y-lg{padding-block:var(--spacing-control-y-lg)}.py-control-y-md{padding-block:var(--spacing-control-y-md)}.py-control-y-sm{padding-block:var(--spacing-control-y-sm)}.py-px{padding-block:1px}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-3\.5{padding-top:calc(var(--spacing) * 3.5)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-3\.5{padding-bottom:calc(var(--spacing) * 3.5)}.pb-4\.5{padding-bottom:calc(var(--spacing) * 4.5)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-2xs{font-size:var(--text-2xs);line-height:var(--tw-leading,var(--text-2xs--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tightest{--tw-tracking:var(--tracking-tightest);letter-spacing:var(--tracking-tightest)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--ui-accent)}.text-canvas{color:var(--ui-canvas)}.text-danger{color:var(--ui-danger)}.text-fg{color:var(--ui-fg)}.text-fg-muted{color:var(--ui-fg-muted)}.text-fg-subtle{color:var(--ui-fg-subtle)}.text-ok{color:var(--ui-ok)}.text-on-accent{color:var(--ui-on-accent)}.text-scope-local{color:var(--ui-scope-local)}.text-scope-managed{color:var(--ui-scope-managed)}.text-scope-project{color:var(--ui-scope-project)}.text-scope-user{color:var(--ui-scope-user)}.text-type-feedback{color:var(--ui-type-feedback)}.text-type-project{color:var(--ui-type-project)}.text-type-reference{color:var(--ui-type-reference)}.text-type-user{color:var(--ui-type-user)}.text-warn{color:var(--ui-warn)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.decoration-danger{-webkit-text-decoration-color:var(--ui-danger);-webkit-text-decoration-color:var(--ui-danger);text-decoration-color:var(--ui-danger)}.decoration-line-strong{-webkit-text-decoration-color:var(--ui-line-strong);-webkit-text-decoration-color:var(--ui-line-strong);text-decoration-color:var(--ui-line-strong)}.accent-accent{accent-color:var(--ui-accent)}.opacity-45{opacity:.45}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow-card{--tw-shadow:var(--ui-shadow-card);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-pop{--tw-shadow:var(--ui-shadow-pop);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-fg-subtle::placeholder{color:var(--ui-fg-subtle)}.backdrop\:bg-scrim::backdrop{background-color:var(--ui-scrim)}.before\:flex-1:before{content:var(--tw-content);flex:1}.before\:border-t:before{content:var(--tw-content);border-top-style:var(--tw-border-style);border-top-width:1px}.before\:border-dashed:before{content:var(--tw-content);--tw-border-style:dashed;border-style:dashed}.before\:border-danger:before{content:var(--tw-content);border-color:var(--ui-danger)}.after\:flex-1:after{content:var(--tw-content);flex:1}.after\:border-t:after{content:var(--tw-content);border-top-style:var(--tw-border-style);border-top-width:1px}.after\:border-dashed:after{content:var(--tw-content);--tw-border-style:dashed;border-style:dashed}.after\:border-danger:after{content:var(--tw-content);border-color:var(--ui-danger)}.first\:mt-0:first-child{margin-top:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.open\:flex:is([open],:popover-open,:open){display:flex}@media (hover:hover){.hover\:border-accent:hover{border-color:var(--ui-accent)}.hover\:border-accent-hover:hover{border-color:var(--ui-accent-hover)}.hover\:border-accent-line:hover{border-color:var(--ui-accent-line)}.hover\:border-line-strong:hover{border-color:var(--ui-line-strong)}.hover\:bg-accent-hover:hover{background-color:var(--ui-accent-hover)}.hover\:bg-danger:hover{background-color:var(--ui-danger)}.hover\:bg-surface-sunken:hover{background-color:var(--ui-surface-sunken)}.hover\:text-accent-hover:hover{color:var(--ui-accent-hover)}.hover\:text-fg:hover{color:var(--ui-fg)}.hover\:text-on-accent:hover{color:var(--ui-on-accent)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-accent:focus{border-color:var(--ui-accent)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-45:disabled{opacity:.45}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:80rem){.xl\:sticky{position:sticky}.xl\:top-4{top:calc(var(--spacing) * 4)}.xl\:max-h-\[calc\(100vh-9rem\)\]{max-height:calc(100vh - 9rem)}.xl\:grid-cols-\[minmax\(280px\,380px\)_1fr\]{grid-template-columns:minmax(280px,380px) 1fr}.xl\:overflow-y-auto{overflow-y:auto}}.dark\:invert:where([data-theme=dark],[data-theme=dark] *){--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.\[\&\>span\]\:block>span{display:block}}:root{--ui-canvas:var(--color-slate-50);--ui-surface:var(--color-slate-0);--ui-surface-sunken:var(--color-slate-100);--ui-surface-raised:var(--color-slate-0);--ui-line:var(--color-slate-200);--ui-line-strong:var(--color-slate-300);--ui-fg:var(--color-slate-900);--ui-fg-muted:var(--color-slate-500);--ui-fg-subtle:var(--color-slate-400);--ui-accent:var(--color-blue-600);--ui-accent-hover:var(--color-blue-700);--ui-accent-surface:var(--color-blue-50);--ui-accent-line:var(--color-blue-200);--ui-on-accent:var(--color-slate-0);--ui-danger:var(--color-red-600);--ui-danger-surface:var(--color-red-50);--ui-danger-line:var(--color-red-300);--ui-warn:var(--color-amber-700);--ui-warn-surface:var(--color-amber-50);--ui-warn-line:var(--color-amber-300);--ui-ok:var(--color-green-600);--ui-ok-surface:var(--color-green-50);--ui-ok-line:var(--color-green-300);--ui-type-project:var(--color-blue-700);--ui-type-project-surface:var(--color-blue-50);--ui-type-feedback:var(--color-amber-700);--ui-type-feedback-surface:var(--color-amber-50);--ui-type-user:var(--color-violet-700);--ui-type-user-surface:var(--color-violet-50);--ui-type-reference:var(--color-green-700);--ui-type-reference-surface:var(--color-green-50);--ui-scope-managed:var(--color-red-600);--ui-scope-managed-surface:var(--color-red-50);--ui-scope-user:var(--color-blue-700);--ui-scope-user-surface:var(--color-blue-50);--ui-scope-project:var(--color-amber-700);--ui-scope-project-surface:var(--color-amber-50);--ui-scope-local:var(--color-slate-600);--ui-scope-local-surface:var(--color-slate-100);--ui-shadow-card:0 1px 2px #0000000d;--ui-shadow-pop:0 1px 2px #0000000f, 0 12px 32px #0000001a;--ui-scrim:#0f172a73}:root[data-theme=dark]{--ui-canvas:var(--color-slate-950);--ui-surface:var(--color-slate-900);--ui-surface-sunken:var(--color-slate-950);--ui-surface-raised:var(--color-slate-800);--ui-line:var(--color-slate-800);--ui-line-strong:var(--color-slate-700);--ui-fg:var(--color-slate-100);--ui-fg-muted:var(--color-slate-400);--ui-fg-subtle:var(--color-slate-500);--ui-accent:var(--color-blue-400);--ui-accent-hover:var(--color-blue-300);--ui-accent-surface:var(--color-blue-950);--ui-accent-line:var(--color-blue-800);--ui-on-accent:var(--color-slate-950);--ui-danger:var(--color-red-400);--ui-danger-surface:var(--color-red-950);--ui-danger-line:var(--color-red-500);--ui-warn:var(--color-amber-400);--ui-warn-surface:var(--color-amber-950);--ui-warn-line:var(--color-amber-600);--ui-ok:var(--color-green-400);--ui-ok-surface:var(--color-green-950);--ui-ok-line:var(--color-green-600);--ui-type-project:var(--color-blue-300);--ui-type-project-surface:var(--color-blue-950);--ui-type-feedback:var(--color-amber-300);--ui-type-feedback-surface:var(--color-amber-950);--ui-type-user:var(--color-violet-300);--ui-type-user-surface:var(--color-violet-950);--ui-type-reference:var(--color-green-300);--ui-type-reference-surface:var(--color-green-950);--ui-scope-managed:var(--color-red-400);--ui-scope-managed-surface:var(--color-red-950);--ui-scope-user:var(--color-blue-300);--ui-scope-user-surface:var(--color-blue-950);--ui-scope-project:var(--color-amber-300);--ui-scope-project-surface:var(--color-amber-950);--ui-scope-local:var(--color-slate-400);--ui-scope-local-surface:var(--color-slate-800);--ui-shadow-card:0 1px 2px #0006;--ui-shadow-pop:0 1px 2px #00000080, 0 12px 32px #00000073;--ui-scrim:#020610b3}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-content:"";--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;--font-mono:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;--color-red-50:oklch(97.1% .013 17.4);--color-red-300:oklch(80.8% .114 19.6);--color-red-400:oklch(70.4% .16 22.2);--color-red-500:oklch(63.7% .208 25.3);--color-red-600:oklch(57.7% .215 27.3);--color-red-950:oklch(25.8% .092 26);--color-amber-50:oklch(97.7% .021 84.6);--color-amber-300:oklch(87.9% .153 91.6);--color-amber-400:oklch(82.8% .171 84.4);--color-amber-600:oklch(66.6% .15 58.3);--color-amber-700:oklch(55.5% .13 49);--color-amber-950:oklch(27.9% .077 45.6);--color-green-50:oklch(98.2% .018 155.8);--color-green-300:oklch(87.1% .12 154.4);--color-green-400:oklch(79.2% .15 151.7);--color-green-600:oklch(58.5% .145 149.2);--color-green-700:oklch(52.7% .132 150.1);--color-green-950:oklch(26.6% .065 152.9);--color-blue-50:oklch(97% .014 253.3);--color-blue-200:oklch(88% .06 253.3);--color-blue-300:oklch(78.4% .124 239.1);--color-blue-400:oklch(75.2% .138 243.7);--color-blue-500:oklch(65.8% .152 248.5);--color-blue-600:oklch(56.5% .163 253.3);--color-blue-700:oklch(48.5% .15 253.3);--color-blue-800:oklch(41% .125 253.3);--color-blue-900:oklch(35.5% .1 253.3);--color-blue-950:oklch(24% .07 253.3);--color-violet-50:oklch(96.9% .016 300);--color-violet-300:oklch(82.7% .104 300);--color-violet-700:oklch(49.6% .19 300);--color-violet-950:oklch(28.3% .109 300);--color-slate-50:oklch(98.4% .003 253.3);--color-slate-100:oklch(96.4% .005 253.3);--color-slate-200:oklch(92.6% .009 253.3);--color-slate-300:oklch(86.6% .014 253.3);--color-slate-400:oklch(70.4% .021 253.3);--color-slate-500:oklch(55.6% .026 253.3);--color-slate-600:oklch(44.8% .028 253.3);--color-slate-700:oklch(36.8% .028 253.3);--color-slate-800:oklch(26.4% .026 253.3);--color-slate-900:oklch(20.4% .024 253.3);--color-slate-950:oklch(14.2% .022 253.3);--spacing:.25rem;--container-2xl:42rem;--text-xs:.6875rem;--text-xs--line-height:1.45;--text-sm:.8125rem;--text-sm--line-height:1.5;--text-base:.875rem;--text-base--line-height:1.6;--text-lg:1rem;--text-lg--line-height:1.5;--text-xl:1.25rem;--text-xl--line-height:1.3;--text-2xl:1.5rem;--text-2xl--line-height:1.2;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-widest:.12em;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.12s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-slate-0:oklch(100% 0 253.3);--spacing-control-x-sm:calc(var(--spacing) * 2);--spacing-control-y-sm:calc(var(--spacing) * 1);--spacing-control-x-md:calc(var(--spacing) * 3);--spacing-control-y-md:calc(var(--spacing) * 2);--spacing-control-x-lg:calc(var(--spacing) * 3.5);--spacing-control-y-lg:calc(var(--spacing) * 2.5);--spacing-control-h-sm:calc(var(--spacing) * 6.5);--spacing-control-h-md:calc(var(--spacing) * 9.5);--spacing-control-h-lg:calc(var(--spacing) * 9.5);--text-2xs:.625rem;--text-2xs--line-height:1.4;--tracking-tightest:-.03em}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{color-scheme:light}:root[data-theme=dark]{color-scheme:dark}html,body{height:100%}body{background-color:var(--ui-canvas);color:var(--ui-fg);font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--text-base--line-height)}::selection{background-color:var(--ui-accent-surface);color:var(--ui-accent)}:focus-visible{outline:2px solid var(--ui-accent);outline-offset:1px}}@layer components{.prose{overflow-wrap:anywhere}.prose>:first-child{margin-top:0}.prose>:last-child{margin-bottom:0}.prose h1,.prose h2,.prose h3,.prose h4{margin:calc(var(--spacing) * 6) 0 calc(var(--spacing) * 2);letter-spacing:var(--tracking-tightest);font-weight:650;line-height:1.25}.prose h1{font-size:var(--text-lg)}.prose h2{font-size:var(--text-base);padding-bottom:calc(var(--spacing) * 1.5);border-bottom:1px solid var(--ui-line)}.prose h3,.prose h4{font-size:var(--text-base);color:var(--ui-fg-muted)}.prose p{margin:calc(var(--spacing) * 3) 0}.prose ul,.prose ol{margin:calc(var(--spacing) * 3) 0;padding-left:calc(var(--spacing) * 5)}.prose ul{list-style-type:"– "}.prose ol{list-style-type:decimal}.prose li{margin:calc(var(--spacing) * 1) 0}.prose li::marker{color:var(--ui-accent);font-family:var(--font-mono)}.prose li>ul,.prose li>ol{margin:calc(var(--spacing) * 1) 0}.prose a{color:var(--ui-accent);text-underline-offset:2px;text-decoration:underline}.prose a:hover{color:var(--ui-accent-hover)}.prose strong{color:var(--ui-fg);font-weight:650}.prose pre{margin:calc(var(--spacing) * 3) 0;padding:calc(var(--spacing) * 3);border:1px solid var(--ui-line);border-radius:var(--radius-md);background-color:var(--ui-surface-sunken);font-size:var(--text-xs);line-height:1.6;overflow-x:auto}.prose code{font-family:var(--font-mono);font-size:.9em}.prose :not(pre)>code{border:1px solid var(--ui-line);border-radius:var(--radius-sm);background-color:var(--ui-surface-sunken);color:var(--ui-accent);padding:1px 4px}.prose blockquote{margin:calc(var(--spacing) * 3) 0;padding-left:calc(var(--spacing) * 3);border-left:2px solid var(--ui-accent-line);color:var(--ui-fg-muted)}.prose hr{margin:calc(var(--spacing) * 5) 0;border:0;border-top:1px dashed var(--ui-line-strong)}.prose table{margin:calc(var(--spacing) * 3) 0;border-collapse:collapse;font-size:var(--text-sm);display:block;overflow-x:auto}.prose th,.prose td{padding:calc(var(--spacing) * 1.5) calc(var(--spacing) * 2.5);border:1px solid var(--ui-line);text-align:left}.prose th{background-color:var(--ui-surface-sunken);font-weight:600}.graph svg{cursor:grab;width:100%;display:block}.graph .node circle{cursor:pointer;stroke-width:1.5px}.graph .node circle.hit{fill:#0000;stroke:none}.graph .node text{fill:var(--ui-fg-muted);font-family:var(--font-mono);pointer-events:none;font-size:9px}.graph .node.hi circle{stroke:var(--ui-accent);stroke-width:2.5px}.graph .node.hi text{fill:var(--ui-fg);font-weight:600}.graph .node.dim{opacity:.18}.graph .node.dim text{display:none}.graph .edge{stroke:var(--ui-line-strong)}.graph .edge.dim{opacity:.05}}@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-y-0{inset-block:0}.top-0{top:0}.top-2{top:calc(var(--spacing) * 2)}.top-3{top:calc(var(--spacing) * 3)}.top-3\.5{top:calc(var(--spacing) * 3.5)}.right-3\.5{right:calc(var(--spacing) * 3.5)}.bottom-2{bottom:calc(var(--spacing) * 2)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-5{bottom:calc(var(--spacing) * 5)}.left-0{left:0}.left-1\/2{left:50%}.left-3\.5{left:calc(var(--spacing) * 3.5)}.z-10{z-index:10}.z-20{z-index:20}.z-200{z-index:200}.float-right{float:right}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.m-auto{margin:auto}.my-1{margin-block:var(--spacing)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-0{margin-top:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.-mb-px{margin-bottom:-1px}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-3\.5{margin-bottom:calc(var(--spacing) * 3.5)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-9{height:calc(var(--spacing) * 9)}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[28rem\]{max-height:28rem}.max-h-\[82vh\]{max-height:82vh}.min-h-20{min-height:calc(var(--spacing) * 20)}.min-h-control-h-lg{min-height:var(--spacing-control-h-lg)}.min-h-control-h-md{min-height:var(--spacing-control-h-md)}.min-h-control-h-sm{min-height:var(--spacing-control-h-sm)}.w-0\.5{width:calc(var(--spacing) * .5)}.w-3{width:calc(var(--spacing) * 3)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-\[calc\(100\%-3rem\)\]{width:calc(100% - 3rem)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.min-w-0{min-width:0}.min-w-6{min-width:calc(var(--spacing) * 6)}.min-w-control-h-sm{min-width:var(--spacing-control-h-sm)}.flex-1{flex:1}.flex-none{flex:none}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.grid-flow-col{grid-auto-flow:column}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[3rem_1fr\]{grid-template-columns:3rem 1fr}.grid-cols-\[280px_1fr\]{grid-template-columns:280px 1fr}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-rows-7{grid-template-rows:repeat(7,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-px{gap:1px}.gap-x-3\.5{column-gap:calc(var(--spacing) * 3.5)}.gap-y-1{row-gap:var(--spacing)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-r-md{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-accent{border-color:var(--ui-accent)}.border-accent-line{border-color:var(--ui-accent-line)}.border-current{border-color:currentColor}.border-danger{border-color:var(--ui-danger)}.border-danger-line{border-color:var(--ui-danger-line)}.border-line{border-color:var(--ui-line)}.border-transparent{border-color:#0000}.border-l-danger{border-left-color:var(--ui-danger)}.border-l-warn{border-left-color:var(--ui-warn)}.bg-accent{background-color:var(--ui-accent)}.bg-accent-surface{background-color:var(--ui-accent-surface)}.bg-canvas{background-color:var(--ui-canvas)}.bg-danger{background-color:var(--ui-danger)}.bg-danger-surface{background-color:var(--ui-danger-surface)}.bg-fg{background-color:var(--ui-fg)}.bg-heat-0{background-color:var(--ui-heat-0)}.bg-heat-1{background-color:var(--ui-heat-1)}.bg-heat-2{background-color:var(--ui-heat-2)}.bg-heat-3{background-color:var(--ui-heat-3)}.bg-heat-4{background-color:var(--ui-heat-4)}.bg-line-strong{background-color:var(--ui-line-strong)}.bg-ok{background-color:var(--ui-ok)}.bg-ok-surface{background-color:var(--ui-ok-surface)}.bg-scope-local-surface{background-color:var(--ui-scope-local-surface)}.bg-scope-managed-surface{background-color:var(--ui-scope-managed-surface)}.bg-scope-project-surface{background-color:var(--ui-scope-project-surface)}.bg-scope-user-surface{background-color:var(--ui-scope-user-surface)}.bg-surface{background-color:var(--ui-surface)}.bg-surface-sunken{background-color:var(--ui-surface-sunken)}.bg-transparent{background-color:#0000}.bg-type-feedback-surface{background-color:var(--ui-type-feedback-surface)}.bg-type-project-surface{background-color:var(--ui-type-project-surface)}.bg-type-reference-surface{background-color:var(--ui-type-reference-surface)}.bg-type-user-surface{background-color:var(--ui-type-user-surface)}.bg-warn{background-color:var(--ui-warn)}.bg-warn-surface{background-color:var(--ui-warn-surface)}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-10{padding:calc(var(--spacing) * 10)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.px-control-x-lg{padding-inline:var(--spacing-control-x-lg)}.px-control-x-md{padding-inline:var(--spacing-control-x-md)}.px-control-x-sm{padding-inline:var(--spacing-control-x-sm)}.px-px{padding-inline:1px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-\[15vh\]{padding-block:15vh}.py-control-y-lg{padding-block:var(--spacing-control-y-lg)}.py-control-y-md{padding-block:var(--spacing-control-y-md)}.py-control-y-sm{padding-block:var(--spacing-control-y-sm)}.py-px{padding-block:1px}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-3\.5{padding-top:calc(var(--spacing) * 3.5)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-3\.5{padding-bottom:calc(var(--spacing) * 3.5)}.pb-4\.5{padding-bottom:calc(var(--spacing) * 4.5)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-2xs{font-size:var(--text-2xs);line-height:var(--tw-leading,var(--text-2xs--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-3{--tw-leading:calc(var(--spacing) * 3);line-height:calc(var(--spacing) * 3)}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tightest{--tw-tracking:var(--tracking-tightest);letter-spacing:var(--tracking-tightest)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--ui-accent)}.text-canvas{color:var(--ui-canvas)}.text-danger{color:var(--ui-danger)}.text-fg{color:var(--ui-fg)}.text-fg-muted{color:var(--ui-fg-muted)}.text-fg-subtle{color:var(--ui-fg-subtle)}.text-ok{color:var(--ui-ok)}.text-on-accent{color:var(--ui-on-accent)}.text-scope-local{color:var(--ui-scope-local)}.text-scope-managed{color:var(--ui-scope-managed)}.text-scope-project{color:var(--ui-scope-project)}.text-scope-user{color:var(--ui-scope-user)}.text-type-feedback{color:var(--ui-type-feedback)}.text-type-project{color:var(--ui-type-project)}.text-type-reference{color:var(--ui-type-reference)}.text-type-user{color:var(--ui-type-user)}.text-warn{color:var(--ui-warn)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.decoration-danger{-webkit-text-decoration-color:var(--ui-danger);-webkit-text-decoration-color:var(--ui-danger);text-decoration-color:var(--ui-danger)}.decoration-line-strong{-webkit-text-decoration-color:var(--ui-line-strong);-webkit-text-decoration-color:var(--ui-line-strong);text-decoration-color:var(--ui-line-strong)}.accent-accent{accent-color:var(--ui-accent)}.opacity-45{opacity:.45}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow-card{--tw-shadow:var(--ui-shadow-card);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-pop{--tw-shadow:var(--ui-shadow-pop);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.outline-2{outline-style:var(--tw-outline-style);outline-width:2px}.outline-offset-1{outline-offset:1px}.outline-fg{outline-color:var(--ui-fg)}.outline-transparent{outline-color:#0000}.transition-\[outline-color\]{transition-property:outline-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-fg-subtle::placeholder{color:var(--ui-fg-subtle)}.backdrop\:bg-scrim::backdrop{background-color:var(--ui-scrim)}.before\:flex-1:before{content:var(--tw-content);flex:1}.before\:border-t:before{content:var(--tw-content);border-top-style:var(--tw-border-style);border-top-width:1px}.before\:border-dashed:before{content:var(--tw-content);--tw-border-style:dashed;border-style:dashed}.before\:border-danger:before{content:var(--tw-content);border-color:var(--ui-danger)}.after\:flex-1:after{content:var(--tw-content);flex:1}.after\:border-t:after{content:var(--tw-content);border-top-style:var(--tw-border-style);border-top-width:1px}.after\:border-dashed:after{content:var(--tw-content);--tw-border-style:dashed;border-style:dashed}.after\:border-danger:after{content:var(--tw-content);border-color:var(--ui-danger)}.first\:mt-0:first-child{margin-top:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.open\:flex:is([open],:popover-open,:open){display:flex}@media (hover:hover){.hover\:border-accent:hover{border-color:var(--ui-accent)}.hover\:border-accent-hover:hover{border-color:var(--ui-accent-hover)}.hover\:border-accent-line:hover{border-color:var(--ui-accent-line)}.hover\:border-line-strong:hover{border-color:var(--ui-line-strong)}.hover\:bg-accent-hover:hover{background-color:var(--ui-accent-hover)}.hover\:bg-danger:hover{background-color:var(--ui-danger)}.hover\:bg-surface-sunken:hover{background-color:var(--ui-surface-sunken)}.hover\:text-accent-hover:hover{color:var(--ui-accent-hover)}.hover\:text-fg:hover{color:var(--ui-fg)}.hover\:text-on-accent:hover{color:var(--ui-on-accent)}.hover\:underline:hover{text-decoration-line:underline}.hover\:outline-fg-subtle:hover{outline-color:var(--ui-fg-subtle)}}.focus\:border-accent:focus{border-color:var(--ui-accent)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-45:disabled{opacity:.45}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:64rem){.lg\:grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.lg\:gap-14{gap:calc(var(--spacing) * 14)}}@media (min-width:80rem){.xl\:sticky{position:sticky}.xl\:top-4{top:calc(var(--spacing) * 4)}.xl\:max-h-\[calc\(100vh-9rem\)\]{max-height:calc(100vh - 9rem)}.xl\:grid-cols-\[minmax\(280px\,380px\)_1fr\]{grid-template-columns:minmax(280px,380px) 1fr}.xl\:overflow-y-auto{overflow-y:auto}}.dark\:invert:where([data-theme=dark],[data-theme=dark] *){--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.\[\&\>span\]\:block>span{display:block}}:root{--ui-canvas:var(--color-slate-50);--ui-surface:var(--color-slate-0);--ui-surface-sunken:var(--color-slate-100);--ui-surface-raised:var(--color-slate-0);--ui-line:var(--color-slate-200);--ui-line-strong:var(--color-slate-300);--ui-fg:var(--color-slate-900);--ui-fg-muted:var(--color-slate-500);--ui-fg-subtle:var(--color-slate-400);--ui-accent:var(--color-blue-600);--ui-accent-hover:var(--color-blue-700);--ui-accent-surface:var(--color-blue-50);--ui-accent-line:var(--color-blue-200);--ui-on-accent:var(--color-slate-0);--ui-danger:var(--color-red-600);--ui-danger-surface:var(--color-red-50);--ui-danger-line:var(--color-red-300);--ui-warn:var(--color-amber-700);--ui-warn-surface:var(--color-amber-50);--ui-warn-line:var(--color-amber-300);--ui-ok:var(--color-green-600);--ui-ok-surface:var(--color-green-50);--ui-ok-line:var(--color-green-300);--ui-heat-0:var(--color-slate-200);--ui-heat-1:var(--color-blue-200);--ui-heat-2:var(--color-blue-400);--ui-heat-3:var(--color-blue-600);--ui-heat-4:var(--color-blue-800);--ui-type-project:var(--color-blue-700);--ui-type-project-surface:var(--color-blue-50);--ui-type-feedback:var(--color-amber-700);--ui-type-feedback-surface:var(--color-amber-50);--ui-type-user:var(--color-violet-700);--ui-type-user-surface:var(--color-violet-50);--ui-type-reference:var(--color-green-700);--ui-type-reference-surface:var(--color-green-50);--ui-scope-managed:var(--color-red-600);--ui-scope-managed-surface:var(--color-red-50);--ui-scope-user:var(--color-blue-700);--ui-scope-user-surface:var(--color-blue-50);--ui-scope-project:var(--color-amber-700);--ui-scope-project-surface:var(--color-amber-50);--ui-scope-local:var(--color-slate-600);--ui-scope-local-surface:var(--color-slate-100);--ui-shadow-card:0 1px 2px #0000000d;--ui-shadow-pop:0 1px 2px #0000000f, 0 12px 32px #0000001a;--ui-scrim:#0f172a73}:root[data-theme=dark]{--ui-canvas:var(--color-slate-950);--ui-surface:var(--color-slate-900);--ui-surface-sunken:var(--color-slate-950);--ui-surface-raised:var(--color-slate-800);--ui-line:var(--color-slate-800);--ui-line-strong:var(--color-slate-700);--ui-fg:var(--color-slate-100);--ui-fg-muted:var(--color-slate-400);--ui-fg-subtle:var(--color-slate-500);--ui-accent:var(--color-blue-400);--ui-accent-hover:var(--color-blue-300);--ui-accent-surface:var(--color-blue-950);--ui-accent-line:var(--color-blue-800);--ui-on-accent:var(--color-slate-950);--ui-danger:var(--color-red-400);--ui-danger-surface:var(--color-red-950);--ui-danger-line:var(--color-red-500);--ui-warn:var(--color-amber-400);--ui-warn-surface:var(--color-amber-950);--ui-warn-line:var(--color-amber-600);--ui-ok:var(--color-green-400);--ui-ok-surface:var(--color-green-950);--ui-ok-line:var(--color-green-600);--ui-heat-0:var(--color-slate-800);--ui-heat-1:var(--color-blue-900);--ui-heat-2:var(--color-blue-700);--ui-heat-3:var(--color-blue-500);--ui-heat-4:var(--color-blue-300);--ui-type-project:var(--color-blue-300);--ui-type-project-surface:var(--color-blue-950);--ui-type-feedback:var(--color-amber-300);--ui-type-feedback-surface:var(--color-amber-950);--ui-type-user:var(--color-violet-300);--ui-type-user-surface:var(--color-violet-950);--ui-type-reference:var(--color-green-300);--ui-type-reference-surface:var(--color-green-950);--ui-scope-managed:var(--color-red-400);--ui-scope-managed-surface:var(--color-red-950);--ui-scope-user:var(--color-blue-300);--ui-scope-user-surface:var(--color-blue-950);--ui-scope-project:var(--color-amber-300);--ui-scope-project-surface:var(--color-amber-950);--ui-scope-local:var(--color-slate-400);--ui-scope-local-surface:var(--color-slate-800);--ui-shadow-card:0 1px 2px #0006;--ui-shadow-pop:0 1px 2px #00000080, 0 12px 32px #00000073;--ui-scrim:#020610b3}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
package/public/ui.mjs CHANGED
@@ -100,7 +100,7 @@ export const sectionLabel = 'mt-5 mb-2 font-mono text-2xs font-semibold uppercas
100
100
  export const note = 'text-xs text-fg-muted';
101
101
  export const noteTight = 'mt-0 mb-2.5 text-xs text-fg-muted';
102
102
 
103
- const memoryItemBase = 'mb-1.5 block w-full cursor-pointer rounded-md border bg-surface px-3 py-2.5 text-left transition-colors';
103
+ const memoryItemBase = 'block min-w-0 flex-1 cursor-pointer rounded-md border bg-surface px-3 py-2.5 text-left transition-colors';
104
104
  const memoryItemState = {
105
105
  active: 'border-accent bg-accent-surface',
106
106
  idle: 'border-line hover:border-accent-line',
@@ -109,6 +109,9 @@ export const memoryItem = (active) => cx(memoryItemBase, active ? memoryItemStat
109
109
  export const memoryTop = 'mb-1 flex items-center gap-2';
110
110
  export const memoryName = 'flex-1 truncate text-sm font-medium text-fg';
111
111
  export const memoryDesc = 'line-clamp-2 text-xs text-fg-muted';
112
+ export const memoryFacts = 'mt-1.5 flex flex-wrap gap-3 font-mono text-2xs text-fg-muted';
113
+ export const memoryFact = (warn) => (warn ? 'text-warn' : 'text-fg-muted');
114
+ export const listItemRow = 'mb-1.5 flex items-start gap-2';
112
115
 
113
116
  export const card = 'rounded-lg border border-line bg-surface p-5 shadow-card';
114
117
  export const detailHead = 'mb-1 flex items-start gap-3';
@@ -189,6 +192,42 @@ const retentionTickTone = { soon: 'bg-warn', safe: 'bg-accent' };
189
192
  export const retentionTick = (soon) => cx(retentionTickBase, soon ? retentionTickTone.soon : retentionTickTone.safe);
190
193
  export const retentionScale = 'mt-1.5 flex justify-between font-mono text-2xs text-fg-subtle';
191
194
 
195
+ export const meterPanels = 'mt-4 grid gap-5 border-t border-line pt-4 lg:grid-cols-[minmax(0,1fr)_auto] lg:gap-14';
196
+ export const meterPanel = 'min-w-0';
197
+ export const meterPanelHead = 'mb-2 flex flex-wrap items-baseline justify-between gap-2';
198
+ export const meterPanelTitle = 'font-mono text-2xs font-semibold uppercase tracking-widest text-fg-subtle';
199
+ export const heatBody = 'flex items-start gap-1.5';
200
+ export const heatDayCol = 'grid grid-rows-7 gap-0.5 pt-4 font-mono text-2xs leading-3 text-fg-subtle';
201
+ export const heatDayLabel = 'h-3 leading-3';
202
+ export const heatMain = 'min-w-0 flex-1';
203
+ export const heatScroll = 'overflow-x-auto pb-1';
204
+ export const heatMonthRow = 'mb-1 grid grid-flow-col justify-start gap-0.5';
205
+ export const heatMonthCell = 'relative h-3 w-3';
206
+ export const heatMonthLabel = 'absolute top-0 left-0 font-mono text-2xs leading-3 whitespace-nowrap text-fg-subtle';
207
+ export const heatGrid = 'grid grid-flow-col grid-rows-7 justify-start gap-0.5';
208
+ export const heatBlank = 'size-3';
209
+
210
+ const heatTileBase = 'size-3 cursor-pointer rounded-xs transition-[outline-color]';
211
+ const heatTone = {
212
+ 0: 'bg-heat-0',
213
+ 1: 'bg-heat-1',
214
+ 2: 'bg-heat-2',
215
+ 3: 'bg-heat-3',
216
+ 4: 'bg-heat-4',
217
+ };
218
+ export const heatTile = (level, selected) => cx(
219
+ heatTileBase,
220
+ pick(heatTone, level, 0),
221
+ selected ? 'outline-2 outline-offset-1 outline-fg' : 'outline-2 outline-offset-1 outline-transparent hover:outline-fg-subtle',
222
+ );
223
+
224
+ export const heatLegend = 'mt-2 flex items-center gap-1 font-mono text-2xs text-fg-subtle';
225
+ export const heatLegendSwatch = (level) => cx('size-3 rounded-xs', pick(heatTone, level, 0));
226
+
227
+ export const sectionLabelRow = 'mt-5 mb-2 flex flex-wrap items-center gap-3 first:mt-0';
228
+ export const sectionLabelInline = 'font-mono text-2xs font-semibold uppercase tracking-widest text-fg-subtle';
229
+ export const heatFilterClear = 'cursor-pointer rounded-md border border-line bg-surface px-1.5 py-0.5 font-mono text-2xs text-fg-muted transition-colors hover:border-line-strong hover:text-fg';
230
+
192
231
  export const provenanceRow = 'mt-0.5 mb-3.5 flex flex-wrap items-baseline gap-1.5 text-xs text-fg-muted';
193
232
  const provenanceLinkBase = 'cursor-pointer rounded-sm border border-transparent bg-transparent px-1 font-medium';
194
233
  const provenanceLinkState = {
@@ -207,9 +246,6 @@ export const issueBody = 'min-w-0 flex-1';
207
246
  export const issueTitle = 'text-sm font-medium text-fg';
208
247
  export const issueDetail = 'font-mono text-2xs break-words text-fg-muted';
209
248
 
210
- export const cutSummary = 'mb-4 rounded-lg border border-danger-line bg-danger-surface px-4 py-3.5';
211
- export const cutSummaryHead = 'mb-1 text-sm font-semibold text-danger';
212
-
213
249
  export const meter = 'mb-5 rounded-lg border border-line bg-surface px-5 py-4';
214
250
  export const meterTop = 'mb-2.5 flex items-baseline gap-2.5';
215
251
  export const meterValue = 'font-mono text-2xl font-semibold tracking-tightest text-fg';
@@ -221,19 +257,11 @@ export const meterNote = 'mt-2.5 text-xs text-fg-muted';
221
257
  export const meterFacts = 'mt-3 flex flex-wrap gap-4 border-t border-line pt-3 font-mono text-2xs text-fg-muted';
222
258
  export const meterFactValue = 'font-semibold text-fg';
223
259
 
224
- export const pruneBar = 'mb-2.5 flex flex-wrap items-center gap-2.5';
225
- export const pruneSpacer = 'flex-1';
260
+ export const listBar = 'mb-2.5 flex flex-wrap items-center gap-2.5';
261
+ export const listSpacer = 'flex-1';
262
+ export const segmentBar = 'mb-5 flex flex-wrap items-center gap-3';
226
263
  export const select = cx('cursor-pointer rounded-md border border-line bg-surface font-mono text-xs text-fg hover:border-line-strong focus:outline-none', controlPad.sm);
227
264
 
228
- const pruneRowBase = 'mb-1 flex cursor-pointer items-center gap-2.5 rounded-md border px-3 py-2 transition-colors';
229
- const pruneRowState = { on: 'border-danger-line bg-danger-surface', off: 'border-line bg-surface hover:border-accent-line' };
230
- export const pruneRow = (on) => cx(pruneRowBase, on ? pruneRowState.on : pruneRowState.off);
231
- export const pruneMain = 'min-w-0 flex-1';
232
- export const pruneName = 'block text-sm font-medium text-fg';
233
- export const pruneDesc = 'block truncate text-xs text-fg-muted';
234
- export const pruneFacts = 'flex flex-none gap-3 font-mono text-2xs text-fg-muted';
235
- export const pruneFact = (warn) => (warn ? 'text-warn' : 'text-fg-muted');
236
-
237
265
  export const dupe = 'mb-2 rounded-lg border border-line bg-surface px-3.5 py-3';
238
266
  export const dupeHead = 'mb-2 flex items-baseline gap-2 font-mono text-2xs text-fg-muted';
239
267
  export const dupeScore = 'font-semibold text-warn';
@@ -283,7 +311,7 @@ export const cascadeDetail = 'block font-mono text-2xs break-words text-fg-muted
283
311
 
284
312
  export const pathInput = cx('my-1 mb-3 w-full rounded-md border border-line bg-surface-sunken font-mono text-xs text-fg focus:border-accent focus:outline-none', controlPad.lg);
285
313
  export const textArea = cx('my-1 mb-1.5 block min-h-20 w-full resize-y rounded-md border border-line bg-surface-sunken font-mono text-xs leading-relaxed text-fg focus:border-accent focus:outline-none', controlPad.lg);
286
- export const hookEditor = 'mb-1.5 rounded-md border border-accent-line bg-surface-sunken px-3 py-2.5';
314
+ export const hookEditor = 'mb-1.5 w-full rounded-md border border-accent-line bg-surface-sunken px-3 py-2.5';
287
315
  export const hookEditorFoot = 'flex justify-end gap-2';
288
316
  export const charCount = 'mb-3 flex items-baseline justify-between gap-3 font-mono text-2xs text-fg-subtle';
289
317
  export const charCountOver = 'mb-3 flex items-baseline justify-between gap-3 font-mono text-2xs text-warn';
@@ -0,0 +1,63 @@
1
+ import * as ui from '/ui.mjs';
2
+ import { node } from '/dom.mjs';
3
+ import { state } from '/state.mjs';
4
+ import { buildWorklist } from '/views/worklist.mjs';
5
+ import { renderCostIssue, COST_KINDS } from '/views/cost-issue.mjs';
6
+ import { renderIssue } from '/views/issue.mjs';
7
+ import { renderPathCheck } from '/views/path-check.mjs';
8
+
9
+ const SHOWN = 40;
10
+
11
+ function renderMeter(container) {
12
+ const { index } = state.store.stats;
13
+ const percent = Math.min(100, index.worstPercent);
14
+
15
+ const note = index.level === 'over'
16
+ ? 'Over the limit. Everything past the cutoff is dropped when the session loads it, so those entries are effectively invisible to Claude right now.'
17
+ : index.level === 'near'
18
+ ? 'Approaching the limit. Once MEMORY.md passes it, everything after the cutoff stops being loaded at all.'
19
+ : 'Comfortably inside the limit. MEMORY.md is loaded at the start of every session.';
20
+
21
+ container.append(node('div', { class: ui.meter }, [
22
+ node('div', { class: ui.meterTop }, [
23
+ node('span', { class: ui.meterValue, text: `${Math.round(index.worstPercent)}%` }),
24
+ node('span', { class: ui.meterUnit, text: `of the MEMORY.md load limit, currently bounded by ${index.limitedBy}` }),
25
+ ]),
26
+ node('div', { class: ui.meterBar }, [
27
+ node('div', { class: ui.meterFill(index.level), style: `width:${percent.toFixed(1)}%` }),
28
+ ]),
29
+ node('p', { class: ui.meterNote, text: note }),
30
+ node('div', { class: ui.meterFacts }, [
31
+ node('span', {}, [node('b', { class: ui.meterFactValue, text: `${index.lines} / ${index.lineLimit}` }), document.createTextNode(' lines')]),
32
+ node('span', {}, [node('b', { class: ui.meterFactValue, text: `${(index.bytes / 1024).toFixed(1)} / ${index.byteLimit / 1024} KB` }), document.createTextNode(' loaded size')]),
33
+ node('span', {}, [node('b', { class: ui.meterFactValue, text: String(index.entryCount) }), document.createTextNode(' index entries')]),
34
+ node('span', {}, [node('b', { class: ui.meterFactValue, text: `~${index.tokens.toLocaleString()}` }), document.createTextNode(' tokens, every session')]),
35
+ ]),
36
+ node('p', { class: ui.meterNote, text: 'Claude Code loads the first 200 lines or 25KB of MEMORY.md, whichever comes first, and drops the rest. Topic files are only read when Claude follows a link, so detail belongs in them and MEMORY.md should stay one line per entry.' }),
37
+ ]));
38
+ }
39
+
40
+ export function renderCleanup(container) {
41
+ const { memories } = state.store;
42
+ renderMeter(container);
43
+
44
+ const items = buildWorklist(state.store);
45
+ if (!items.length) {
46
+ container.append(node('div', { class: ui.card }, [
47
+ node('p', { class: ui.okLine, text: '✓ Nothing to fix.' }),
48
+ node('p', { class: ui.noteTight, text: 'MEMORY.md is inside its load limit, every memory file is referenced by it, every pointer resolves, and every [[wikilink]] finds its target.' }),
49
+ ]));
50
+ } else {
51
+ container.append(node('div', { class: ui.sectionLabel, text: `Worst first · ${items.length}` }));
52
+ for (const item of items.slice(0, SHOWN)) {
53
+ const row = COST_KINDS.has(item.kind) ? renderCostIssue(item) : renderIssue(item, memories);
54
+ if (row) container.append(row);
55
+ }
56
+ if (items.length > SHOWN) {
57
+ container.append(node('p', { class: ui.note, text: `${items.length - SHOWN} more not listed. Fix some of the above and they move up.` }));
58
+ }
59
+ }
60
+
61
+ container.append(node('div', { class: ui.sectionLabel, text: 'Beyond the memory directory' }));
62
+ renderPathCheck(container);
63
+ }