Repository navigation
Expand file tree
/
Copy pathdrawer.html
More file actions
562 lines (533 loc) · 49.1 KB
/
Copy pathdrawer.html
File metadata and controls
562 lines (533 loc) · 49.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
<!-- DeepLore — Drawer Panel -->
<!-- ═══════════════════════════════════════════════════════════════════════════
ZONE 1: Fixed Status (always visible)
═══════════════════════════════════════════════════════════════════════════ -->
<div id="dle-drawer-status" class="dle-drawer-zone dle-zone-status" role="status" aria-label="DeepLore status" data-i18n="[aria-label]dle_drawer_status_aria">
<!-- Status + stats row. Not a live region itself: phase/status changes are announced once,
at polite urgency, through the dedicated visually-hidden #dle-drawer-live region
(announceToScreenReader). Nesting live regions here double-announced (f106). -->
<div class="dle-status-row" aria-atomic="true">
<!-- f028: the live-changing phase label is grouped with the activity dot on its own
non-wrapping line; the static stats live in a separate group that no longer
reflows when the localized phase string changes width (de/ru run long). -->
<div class="dle-status-activity">
<span class="dle-status-dot dle-clickable-status" title="System status — click for full status" role="button" tabindex="0" aria-label="System status: loading. Click to open status." data-i18n="[title]dle_status_dot_tooltip"></span>
<span class="dle-pipeline-label dle-clickable-status" aria-label="Activity" role="button" tabindex="0" title="Click to open full status (/dle-status)" data-i18n="dle_status_idle;[aria-label]dle_librarian_activity_tab">Idle</span>
</div>
<div class="dle-status-stats">
<span class="dle-stat-divider" aria-hidden="true">|</span>
<span class="dle-stat" data-stat="entries" title="Vault entries indexed" aria-label="0 vault entries indexed" data-i18n="[title]dle_stat_entries_tooltip">0</span>
<span class="dle-stat" data-stat="mode" title="AI search mode" aria-label="Search mode: loading" data-i18n="[title]dle_stat_mode_tooltip">—</span>
</div>
</div>
<!-- Wave C: divider + muted label group the two budget bars into one calm "Budget" cluster,
visually distinct from the activity status-row above. Calm, never an alarm. -->
<div class="dle-zone-divider dle-budget-divider" aria-hidden="true"></div>
<div class="dle-budget-cluster-label" aria-hidden="true" data-i18n="dle_budget_cluster_label">Budget</div>
<!-- Token budget bar -->
<div class="dle-token-bar-container" role="progressbar" aria-valuenow="0" aria-valuemax="1" aria-valuemin="0"
aria-label="Lore Budget — how many tokens DeepLore used for lore injection vs your configured budget limit">
<div class="dle-token-bar" style="width: 0%;"></div>
<span class="dle-token-bar-label" data-i18n="dle_token_bar_waiting">Lore | waiting…</span>
</div>
<!-- B2: soft, non-alarm note shown only when the token budget actually cost lore (truncation). -->
<div class="dle-bar-note dle-token-bar-note dle-hidden"></div>
<!-- Max entries bar -->
<div class="dle-entries-bar-container" role="progressbar" aria-valuenow="0" aria-valuemax="1" aria-valuemin="0"
aria-label="Entry count — how many entries were injected vs your configured max entries limit">
<div class="dle-entries-bar" style="width: 0%;"></div>
<span class="dle-entries-bar-label" data-i18n="dle_entries_bar_waiting">Entries | waiting…</span>
</div>
<!-- B2: soft note shown only when the entry cap actually cost lore ("N of M shown"). -->
<div class="dle-bar-note dle-entries-bar-note dle-hidden"></div>
<!-- Active gating filters (only shown when set) -->
<div class="dle-active-filters" aria-label="Active gating filters"></div>
<!-- Active gating filters end the status (passive readout) zone. Quick actions moved below. -->
</div>
<!-- ═══════════════════════════════════════════════════════════════════════════
ZONE 1b: Quick Actions — D4 (v2.5 Wave 3): lifted OUT of the role="status"
aria-live region above, so button label changes (e.g. "Skip Librarian" →
"Skipping Next") are NOT announced as status. The status zone stays a passive
readout. Handlers delegate from the $drawer root (wireStatusActions), so the
relocation is transparent to event wiring. See docs/gotchas.md #75.
═══════════════════════════════════════════════════════════════════════════ -->
<div id="dle-drawer-actions" class="dle-zone-actions">
<div class="dle-action-row" role="toolbar" aria-label="Quick actions" aria-orientation="horizontal">
<button type="button" class="menu_button menu_button_icon dle-action-btn dle-action-btn-labeled" data-action="refresh" title="Reload lore from Obsidian" aria-label="Reload lore from Obsidian" data-i18n="[title]dle_refresh_tooltip;[aria-label]dle_refresh_tooltip">
<i class="fa-solid fa-arrows-rotate" aria-hidden="true"></i>
<span class="dle-action-label" data-i18n="dle_common_refresh">Refresh</span>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn" data-action="scribe" title="Run Session Scribe — AI summarizes the conversation and saves notes to Obsidian" aria-label="Run Session Scribe" data-i18n="[title]dle_scribe_action_tooltip">
<i class="fa-solid fa-feather-pointed" aria-hidden="true"></i>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn" data-action="newlore" title="Create new lore entry" aria-label="Create new lore entry" data-i18n="[title]dle_newlore_tooltip;[aria-label]dle_newlore_tooltip">
<i class="fa-solid fa-plus" aria-hidden="true"></i>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn" data-action="librarian-chat" title="Open Librarian chat" aria-label="Open Librarian chat" data-i18n="[title]dle_librarian_chat_tooltip;[aria-label]dle_librarian_chat_tooltip">
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn" data-action="graph" title="Open relationship graph" aria-label="Open relationship graph" data-i18n="[title]dle_graph_tooltip;[aria-label]dle_graph_tooltip">
<i class="fa-solid fa-diagram-project" aria-hidden="true"></i>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn dle-action-btn-labeled" data-action="clear-picks" title="Reroll lore picks — clears AI search cache so next generation re-selects from scratch" aria-label="Reroll lore picks (clear AI search cache)" data-i18n="[title]dle_reroll_tooltip">
<i class="fa-solid fa-shuffle" aria-hidden="true"></i>
<span class="dle-action-label" data-i18n="dle_reroll_button">Reroll Lore</span>
</button>
<button type="button" class="menu_button menu_button_icon dle-action-btn dle-action-btn-labeled" data-action="skip-tools" title="Skip Librarian tools for next generation" aria-label="Skip Librarian tools for next generation" data-i18n="[title]dle_skip_librarian_tooltip;[aria-label]dle_skip_librarian_tooltip">
<i class="fa-solid fa-ban" aria-hidden="true"></i>
<span class="dle-action-label" data-i18n="dle_skip_librarian_button">Skip Librarian</span>
</button>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════════════════════
Separator
═══════════════════════════════════════════════════════════════════════════ -->
<div class="dle-zone-divider" aria-hidden="true"></div>
<!-- ═══════════════════════════════════════════════════════════════════════════
ZONE 2: Tabbed Content
═══════════════════════════════════════════════════════════════════════════ -->
<div id="dle-drawer-tabs" class="dle-drawer-zone dle-zone-tabs">
<!-- Tab bar -->
<div class="dle-tab-bar" role="tablist" aria-label="DeepLore panels" aria-orientation="horizontal">
<button type="button" class="dle-tab active" id="dle-tab-injection" data-tab="injection" role="tab"
aria-selected="true" aria-controls="dle-panel-injection" aria-label="Injection — see which lore was included in the last message and why" tabindex="0">
<i class="fa-solid fa-circle-question" aria-hidden="true"></i>
<span class="dle-tab-text" data-i18n="dle_tab_injection">Injection</span>
<span class="dle-tab-badge" data-badge="injection" aria-hidden="true"></span>
</button>
<button type="button" class="dle-tab" id="dle-tab-browse" data-tab="browse" role="tab"
aria-selected="false" aria-controls="dle-panel-browse" aria-label="Browse — search and manage all lore entries in your vault" tabindex="-1">
<i class="fa-solid fa-book-open" aria-hidden="true"></i>
<span class="dle-tab-text" data-i18n="dle_common_browse">Browse</span>
<span class="dle-tab-badge" data-badge="browse" aria-hidden="true"></span>
</button>
<button type="button" class="dle-tab" id="dle-tab-gating" data-tab="gating" role="tab"
aria-selected="false" aria-controls="dle-panel-gating" aria-label="Filters — set contextual gating fields" tabindex="-1">
<i class="fa-solid fa-filter" aria-hidden="true"></i>
<span class="dle-tab-text" data-i18n="dle_gating_tab_label">Filters</span>
<span class="dle-tab-badge" data-badge="gating" aria-hidden="true"></span>
</button>
<button type="button" class="dle-tab" id="dle-tab-librarian" data-tab="librarian" role="tab"
aria-selected="false" aria-controls="dle-panel-librarian" aria-label="Librarian — lore gap inbox and draft review" tabindex="-1">
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
<span class="dle-tab-text" data-i18n="dle_analytics_section_librarian">Librarian</span>
<span class="dle-tab-badge dle-librarian-badge" data-badge="librarian" aria-hidden="true"></span>
</button>
<button type="button" class="dle-tab" id="dle-tab-tools" data-tab="tools" role="tab"
aria-selected="false" aria-controls="dle-panel-tools" aria-label="Tools — diagnostics, AI tools, and data management" tabindex="-1">
<i class="fa-solid fa-toolbox" aria-hidden="true"></i>
<span class="dle-tab-text" data-i18n="dle_librarian_tools_h4">Tools</span>
</button>
</div>
<!-- Active tab label — text is mirrored from the active tab's localized .dle-tab-text by
switchTab(); NO data-i18n here (it would fight that JS write — see drawer-events.js). -->
<div class="dle-tab-label" aria-hidden="true">Injection</div>
<!-- ─── Tab: Injection (explains injection decisions) ─── -->
<div class="dle-tab-panel active" id="dle-panel-injection" data-tab="injection"
role="tabpanel" aria-labelledby="dle-tab-injection">
<div class="dle-panel-toolbar">
<div class="dle-why-filter-toggle" role="radiogroup" aria-label="Filter entries" data-i18n="[aria-label]dle_why_filter_aria">
<button type="button" class="dle-why-filter-btn active" data-filter="injected" role="radio" aria-checked="true" tabindex="0" data-i18n="dle_analytics_col_injected">Injected</button>
<button type="button" class="dle-why-filter-btn" data-filter="filtered" role="radio" aria-checked="false" tabindex="-1" data-i18n="dle_why_filter_filtered">Filtered</button>
<button type="button" class="dle-why-filter-btn" data-filter="both" role="radio" aria-checked="false" tabindex="-1" data-i18n="dle_why_filter_both">Both</button>
</div>
<span class="dle-section-diff"></span>
<button type="button" class="menu_button_icon dle-copy-titles-btn" data-action="copy-titles" title="Copy injected entry titles to clipboard" aria-label="Copy injected entry titles to clipboard" data-i18n="[title]dle_copy_titles_tooltip;[aria-label]dle_copy_titles_tooltip">
<i class="fa-solid fa-clipboard" aria-hidden="true"></i>
</button>
<button type="button" class="dle-tab-expand" data-expand="injection" title="Open full details popup (/dle-why)" aria-label="Open full details popup" data-i18n="[title]dle_full_view_tooltip">
Full View <i class="fa-solid fa-up-right-from-square" aria-hidden="true"></i>
</button>
</div>
<!-- Verdict funnel: N matched → N picked → N injected (populated by renderInjectionTab; only shown when a trace exists) -->
<div class="dle-why-funnel" role="status" aria-live="polite" hidden></div>
<!-- Injected entries -->
<div class="dle-why-list" role="list" aria-label="Injected entries — why these were included" data-i18n="[aria-label]dle_why_list_aria"></div>
<!-- Rejected entries (why not) -->
<div class="dle-why-not-section">
<div class="dle-why-not-header dle-text-sm dle-muted">
<i class="fa-solid fa-filter-circle-xmark" aria-hidden="true"></i> <span data-i18n="dle_why_filtered_out_header">Filtered Out</span>
</div>
<div class="dle-why-not-list" role="list" aria-label="Filtered entries — why these were excluded" data-i18n="[aria-label]dle_why_not_list_aria"></div>
</div>
<!-- Empty state (shown when no pipeline has run) -->
<div class="dle-empty-state dle-visible">
<i class="fa-solid fa-circle-question" aria-hidden="true"></i>
<p data-i18n="dle_empty_injection">No entries injected yet.</p>
<div class="dle-empty-guide">
<p data-i18n="dle_empty_guide_intro">To see lore injection in action:</p>
<ol>
<li data-i18n-html="dle_empty_guide_step_1">Connect to an Obsidian vault with <code>#lorebook</code>-tagged entries</li>
<li data-i18n="dle_empty_guide_step_2">Send a message mentioning a keyword from your entries</li>
<li data-i18n="dle_empty_guide_step_3">This tab will show which entries were injected and why</li>
</ol>
<div class="dle-empty-cta-row">
<button type="button" class="menu_button dle-empty-cta-btn" data-empty-action="setup" title="Guided setup wizard" data-i18n="[title]dle_drawer_tool_setup_wizard_tooltip">
<i class="fa-solid fa-hat-wizard" aria-hidden="true"></i> <span data-i18n="dle_empty_cta_setup">Open Setup Wizard</span>
</button>
<button type="button" class="menu_button dle-empty-cta-btn" data-empty-action="import-wi" title="Import World Info (lorebook) entries from SillyTavern to Obsidian" data-i18n="[title]dle_import_wi_tooltip">
<i class="fa-solid fa-file-import" aria-hidden="true"></i> <span data-i18n="dle_empty_cta_import">Import from World Info</span>
</button>
</div>
<p class="dle-empty-commands dle-text-xs dle-muted" data-i18n-html="dle_empty_cta_hint">Prefer commands? Use <code>/dle-setup</code> or <code>/dle-import</code>.</p>
</div>
</div>
<!-- Entry Timers (cooldown, decay) — collapsible -->
<details class="dle-why-timers-section">
<summary class="dle-why-timers-toggle">
<i class="fa-solid fa-clock" aria-hidden="true"></i> <span data-i18n="dle_entry_timers_summary">Entry Timers</span>
</summary>
<div class="dle-timer-list" role="list" aria-label="Active entry timers (cooldown, rotation, and minimum trigger count)" data-i18n="[aria-label]dle_timer_list_aria"></div>
<div class="dle-timer-empty dle-text-sm dle-visible" style="opacity: 0.5; padding: 4px 0;" data-i18n="dle_no_active_timers">No active timers</div>
</details>
</div>
<!-- ─── Tab: Browse ─── -->
<div class="dle-tab-panel" id="dle-panel-browse" data-tab="browse"
role="tabpanel" aria-labelledby="dle-tab-browse">
<div class="dle-panel-toolbar">
<input type="text" class="text_pole dle-browse-input" placeholder="Search entries... (/)" aria-label="Search vault entries" data-i18n="[aria-label]dle_browse_search_aria">
<button type="button" class="menu_button menu_button_icon dle-browse-search-help" title="Search syntax: plain text matches title/keys/content. Prefixed: tag:wizard, folder:Locations, key:apple, summary:"old gods", field:era=medieval. Combine multiple prefixes with spaces." aria-label="Browse search syntax help" data-i18n="[title]dle_browse_search_syntax_tooltip;[aria-label]dle_browse_search_syntax_aria">
<i class="fa-solid fa-circle-question" aria-hidden="true"></i>
</button>
<goo-spinner class="dle-browse-refresh-spinner" size="28" color="currentColor" aria-hidden="true" title="Refreshing vault index..." data-i18n="[title]dle_browse_refreshing_spinner_tooltip"></goo-spinner>
<button type="button" class="dle-tab-expand" data-expand="browse" title="Open full Browse popup" aria-label="Open full Browse popup" data-i18n="[title]dle_browse_full_view_tooltip;[aria-label]dle_browse_full_view_tooltip">
Full View <i class="fa-solid fa-up-right-from-square" aria-hidden="true"></i>
</button>
</div>
<details class="dle-browse-search-help-popover">
<summary class="dle-text-xs dle-muted" data-i18n="dle_search_syntax_summary">Search syntax</summary>
<div class="dle-text-xs dle-muted dle-search-syntax-grid">
<div data-i18n-html="dle_search_syntax_tag_example"><code>tag:wizard</code> — entries tagged <em>wizard</em></div>
<div data-i18n-html="dle_search_syntax_folder_example"><code>folder:Locations</code> — entries under <em>Locations/</em></div>
<div data-i18n-html="dle_search_syntax_key_example"><code>key:apple</code> — keyword exact-match</div>
<div data-i18n-html="dle_search_syntax_summary_example"><code>summary:"old gods"</code> — phrase in summary</div>
<div data-i18n-html="dle_search_syntax_field_example"><code>field:era=medieval</code> — custom-field match</div>
<div data-i18n="dle_search_syntax_combine">Combine prefixes with spaces. Plain words match title/keys/content.</div>
</div>
</details>
<div class="dle-browse-filters">
<select class="text_pole dle-browse-filter-select" data-filter="status" aria-label="Filter by status" data-i18n="[aria-label]dle_status_filter_aria">
<option value="all" data-i18n="dle_status_all">Status (all)</option>
<option value="injected" data-i18n="dle_analytics_col_injected">Injected</option>
<option value="pinned" data-i18n="dle_common_pinned">Pinned</option>
<option value="blocked" data-i18n="dle_common_blocked">Blocked</option>
<option value="constant" data-i18n="dle_graph_filter_type_constant">Constant</option>
<option value="seed" data-i18n="dle_graph_filter_type_seed">Seed</option>
<option value="bootstrap" data-i18n="dle_browse_filter_bootstrap">Bootstrap</option>
<option value="never_injected" data-i18n="dle_browse_filter_never_injected">Never Injected</option>
</select>
<select class="text_pole dle-browse-filter-select" data-filter="tag" aria-label="Filter by tag" data-i18n="[aria-label]dle_tag_filter_aria">
<option value="" data-i18n="dle_tags_all">Tags (all)</option>
</select>
<select class="text_pole dle-browse-filter-select" data-filter="folder" aria-label="Filter by folder" data-i18n="[aria-label]dle_browse_filter_folder_aria">
<option value="" data-i18n="dle_browse_filter_folder_all">Folder (all)</option>
</select>
<span class="dle-browse-custom-filters"></span>
<select class="text_pole dle-browse-sort-select" data-sort aria-label="Sort entries by priority, name, or token count" data-i18n="[aria-label]dle_sort_aria">
<option value="priority_asc" data-i18n="dle_sort_priority">Default (Priority)</option>
<option value="priority_desc" data-i18n="dle_sort_priority_desc">Priority ↓</option>
<option value="alpha_asc" data-i18n="dle_sort_alpha_asc">A → Z</option>
<option value="alpha_desc" data-i18n="dle_sort_alpha_desc">Z → A</option>
<option value="tokens_desc" data-i18n="dle_sort_tokens_desc">Tokens ↓</option>
<option value="tokens_asc" data-i18n="dle_sort_tokens_asc">Tokens ↑</option>
<option value="injections_desc" data-i18n="dle_sort_injections_desc">Injections ↓</option>
</select>
</div>
<div class="dle-browse-batch-toolbar" role="toolbar" aria-label="View & batch actions">
<button type="button" class="menu_button menu_button_icon dle-browse-group-toggle" data-pressed="false" aria-pressed="false" title="Group entries by top-level folder" data-i18n="[title]dle_group_toggle_tooltip">
<i class="fa-solid fa-folder-tree" aria-hidden="true"></i>
<span class="dle-toolbar-label" data-i18n="dle_group_button_label">Group</span>
</button>
<button type="button" class="menu_button menu_button_icon dle-browse-expand-all-toggle" hidden title="Expand all folders" data-i18n="[title]dle_expand_all_tooltip">
<i class="fa-solid fa-chevron-down" aria-hidden="true"></i>
<span class="dle-toolbar-label" data-i18n="dle_expand_all_label">Expand all</span>
</button>
<button type="button" class="menu_button menu_button_icon dle-browse-select-toggle" data-pressed="false" aria-pressed="false" title="Show row checkboxes for multi-select" data-i18n="[title]dle_select_toggle_tooltip">
<i class="fa-solid fa-square-check" aria-hidden="true"></i>
<span class="dle-toolbar-label" data-i18n="dle_cmd_setera_popup_title">Select</span>
</button>
<button type="button" class="menu_button dle-browse-optimize-selected" hidden title="Run AI keyword optimization on every selected entry (one popup per entry)" data-i18n="[title]dle_optimize_selected_tooltip">
<i class="fa-solid fa-wand-magic-sparkles" aria-hidden="true"></i>
<span class="dle-browse-optimize-count" data-i18n="dle_optimize_selected_label">Optimize Selected (0)</span>
</button>
<button type="button" class="menu_button menu_button_icon dle-browse-clear-selection" hidden title="Clear selection" data-i18n="[title]dle_clear_selection_tooltip">
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
</button>
</div>
<div class="dle-browse-quick-filters" role="toolbar" aria-label="Quick filters"></div>
<div class="dle-browse-summary dle-text-sm dle-muted" aria-live="polite"></div>
<div class="dle-browse-list" role="list" aria-label="Vault entries" data-i18n="[aria-label]dle_browse_list_aria"></div>
<!-- Empty state: loading vault entries -->
<div class="dle-empty-state" id="dle-browse-loading">
<goo-spinner size="72" color="currentColor" aria-hidden="true"></goo-spinner>
<p data-i18n="dle_browse_loading">Loading vault entries...</p>
</div>
<!-- Empty state: no entries loaded -->
<div class="dle-empty-state dle-visible" id="dle-browse-empty-no-data">
<i class="fa-solid fa-database" aria-hidden="true"></i>
<p data-i18n="dle_browse_no_data">No entries indexed.</p>
<div class="dle-empty-guide">
<p data-i18n-html="dle_browse_no_data_intro">Your vault needs notes tagged with <code>#lorebook</code>. Each entry must include:</p>
<ul>
<li data-i18n-html="dle_browse_no_data_step_tags"><code>tags: [lorebook]</code> in frontmatter</li>
<li data-i18n-html="dle_browse_no_data_step_keys"><code>keys: [keyword1, keyword2]</code> for matching</li>
</ul>
<div class="dle-empty-cta-row">
<button type="button" class="menu_button dle-empty-cta-btn" data-empty-action="setup" title="Guided setup wizard" data-i18n="[title]dle_drawer_tool_setup_wizard_tooltip">
<i class="fa-solid fa-hat-wizard" aria-hidden="true"></i> <span data-i18n="dle_empty_cta_setup">Open Setup Wizard</span>
</button>
<button type="button" class="menu_button dle-empty-cta-btn" data-empty-action="import-wi" title="Import World Info (lorebook) entries from SillyTavern to Obsidian" data-i18n="[title]dle_import_wi_tooltip">
<i class="fa-solid fa-file-import" aria-hidden="true"></i> <span data-i18n="dle_empty_cta_import">Import from World Info</span>
</button>
</div>
<p class="dle-empty-commands dle-text-xs dle-muted" data-i18n-html="dle_empty_cta_hint">Prefer commands? Use <code>/dle-setup</code> or <code>/dle-import</code>.</p>
</div>
</div>
<!-- Empty state: filters returned no results -->
<div class="dle-empty-state" id="dle-browse-empty-no-results">
<i class="fa-solid fa-filter-circle-xmark" aria-hidden="true"></i>
<div class="dle-browse-empty-no-results">
<p data-i18n="dle_browse_no_results">No entries match your filters.</p>
<p class="dle-browse-active-filters-list"></p>
<button type="button" class="dle-browse-clear-filters" data-i18n="dle_clear_filters_button">Clear all filters</button>
</div>
</div>
</div>
<!-- ─── Tab: Gating ─── -->
<div class="dle-tab-panel" id="dle-panel-gating" data-tab="gating"
role="tabpanel" aria-labelledby="dle-tab-gating">
<div class="dle-panel-toolbar">
<span class="dle-text-sm" data-i18n="dle_gating_tab_label">Filters</span>
<button type="button" class="menu_button menu_button_icon dle-clear-all-gating-btn" title="Clear all active gating filters" aria-label="Clear all gating filters" data-i18n="[title]dle_clear_all_gating_tooltip">
<i class="fa-solid fa-eraser" aria-hidden="true"></i>
</button>
<button type="button" class="menu_button menu_button_icon dle-manage-fields-btn" title="Add, remove, or configure custom gating fields" aria-label="Manage field definitions" data-i18n="[title]dle_manage_fields_tooltip">
<i class="fa-solid fa-gear" aria-hidden="true"></i>
</button>
<button type="button" class="dle-tab-expand" data-expand="gating" title="Open full Context State popup" aria-label="Open full Context State popup" data-i18n="[title]dle_context_state_popup_tooltip;[aria-label]dle_context_state_popup_tooltip">
Full View <i class="fa-solid fa-up-right-from-square" aria-hidden="true"></i>
</button>
</div>
<div class="dle-gating-folder-section" aria-label="Folder filter" data-i18n="[aria-label]dle_folder_filter_aria">
<div class="dle-gating-folder-header">
<span class="dle-gating-dot dle-gating-dot-empty dle-folder-dot" aria-hidden="true"></span>
<span class="dle-gating-label" data-i18n="dle_folder_filter_label">Folder Filter</span>
<button type="button" class="menu_button menu_button_icon dle-folder-set-btn" title="Select folders to filter by" aria-label="Select folders" data-i18n="[title]dle_folder_set_tooltip">
<i class="fa-solid fa-plus-circle" aria-hidden="true"></i>
</button>
</div>
<div class="dle-folder-chips" aria-label="Active folder filters" data-i18n="[aria-label]dle_folder_chips_aria"></div>
<div class="dle-folder-empty dle-gating-empty" data-i18n="dle_all_folders_active">All folders active</div>
</div>
<div class="dle-gating-fields-container" aria-label="Contextual gating fields" data-i18n="[aria-label]dle_gating_fields_aria">
<!-- Dynamically populated by renderGatingTab() based on fieldDefinitions -->
</div>
</div>
<!-- ─── Tab: Librarian (lore gap inbox) ─── -->
<div class="dle-tab-panel" id="dle-panel-librarian" data-tab="librarian"
role="tabpanel" aria-labelledby="dle-tab-librarian">
<div class="dle-panel-toolbar">
<div class="dle-librarian-sub-tabs" role="radiogroup" aria-label="Librarian view" data-i18n="[aria-label]dle_librarian_view_aria">
<button type="button" class="dle-librarian-sub-tab active" data-filter="flag" role="radio" aria-checked="true"><span data-i18n="dle_librarian_flags_tab">Flags</span> <span class="dle-sub-tab-count"></span></button>
<button type="button" class="dle-librarian-sub-tab" data-filter="activity" role="radio" aria-checked="false"><span data-i18n="dle_librarian_activity_tab">Activity</span> <span class="dle-sub-tab-count"></span></button>
</div>
<div class="dle-librarian-toolbar-right">
<select class="text_pole dle-librarian-sort" data-sort aria-label="Sort by" data-i18n="[aria-label]dle_librarian_sort_aria">
<option value="newest" data-i18n="dle_sort_newest">Newest</option>
<option value="frequency" data-i18n="dle_graph_color_mode_frequency">Frequency</option>
<option value="urgency" data-i18n="dle_sort_urgency">Urgency</option>
</select>
</div>
</div>
<!-- f041: contextual bulk-action bar. Select-all + count are always shown; the action
cluster reveals only when rows are picked (.dle-has-selection toggled in render).
Action buttons (Open/Done/Remove) + Clear/Invert are delegated in drawer-events.js,
so they work identically here as in the retired standalone action row below. -->
<div class="dle-librarian-select-all-bar" role="group" aria-label="Bulk selection" data-i18n="[aria-label]dle_bulk_selection_aria">
<label class="dle-librarian-select-all-label">
<input type="checkbox" class="dle-librarian-select-all" aria-label="Toggle select all" data-i18n="[aria-label]dle_select_all_aria">
<span data-i18n="dle_select_all_aria">Toggle select all</span>
</label>
<span class="dle-librarian-select-count dle-text-xs dle-muted" aria-live="polite"></span>
<div class="dle-librarian-bulk-actions" role="group" aria-label="Selection actions" data-i18n="[aria-label]dle_librarian_bulk_actions_aria">
<button type="button" class="dle-librarian-bulk-btn dle-librarian-action" data-librarian-action="open" title="Open the selected gap in the Librarian editor" aria-label="Open selected gap" disabled data-i18n="[title]dle_librarian_open_tooltip;[aria-label]dle_librarian_open_label">
<i class="fa-solid fa-pen-to-square" aria-hidden="true"></i> <span data-i18n="dle_librarian_open_label">Open</span>
</button>
<button type="button" class="dle-librarian-bulk-btn dle-librarian-action" data-librarian-action="done" title="Mark selected as written" aria-label="Mark selected as written" disabled data-i18n="[title]dle_librarian_done_tooltip;[aria-label]dle_librarian_mark_done_label">
<i class="fa-solid fa-check" aria-hidden="true"></i> <span data-i18n="dle_librarian_mark_done_label">Mark Done</span>
</button>
<button type="button" class="dle-librarian-bulk-btn dle-librarian-action dle-librarian-bulk-btn-danger" data-librarian-action="remove" title="Remove (hide on first click, dismiss forever on second)" aria-label="Remove selected" disabled data-i18n="[title]dle_librarian_remove_tooltip;[aria-label]dle_librarian_remove_label">
<i class="fa-solid fa-trash" aria-hidden="true"></i> <span data-i18n="dle_librarian_remove_label">Remove</span>
</button>
<span class="dle-librarian-bulk-sep" aria-hidden="true"></span>
<button type="button" class="dle-librarian-bulk-btn dle-librarian-bulk-btn-ghost dle-librarian-invert-btn" title="Invert selection" aria-label="Invert selection" data-i18n="[title]dle_librarian_invert_tooltip;[aria-label]dle_librarian_invert_label"><span data-i18n="dle_librarian_invert_label">Invert</span></button>
<button type="button" class="dle-librarian-bulk-btn dle-librarian-bulk-btn-ghost dle-librarian-clear-btn" title="Clear selection" aria-label="Clear selection" data-i18n="[title]dle_clear_selection_tooltip;[aria-label]dle_clear_selection_tooltip"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button>
</div>
</div>
<div class="dle-librarian-list" role="list" aria-label="Librarian activity" data-i18n="[aria-label]dle_librarian_list_aria"></div>
<div class="dle-empty-state dle-visible" id="dle-librarian-empty">
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
<p class="dle-librarian-empty-text" data-i18n="dle_librarian_empty">No lore gaps recorded yet.</p>
<div class="dle-librarian-empty-actions">
<button type="button" id="dle-librarian-new-entry-btn-empty" class="menu_button dle-tool-btn dle-librarian-new-entry-btn" data-action="librarian-new" title="Create a new vault entry from scratch" data-i18n="[title]dle_new_entry_empty_tooltip">
<i class="fa-solid fa-plus" aria-hidden="true"></i> <span data-i18n="dle_librarian_new_entry_label">New Entry</span>
</button>
<button type="button" class="menu_button dle-tool-btn dle-librarian-vault-review-btn" data-action="librarian-review" title="AI-guided review of your vault" data-i18n="[title]dle_vault_review_tooltip">
<i class="fa-solid fa-wand-magic-sparkles" aria-hidden="true"></i> <span data-i18n="dle_librarian_vault_review_label">Vault Review</span>
</button>
</div>
</div>
<div class="dle-librarian-toolbar-bottom">
<button type="button" id="dle-librarian-new-entry-btn-toolbar" class="menu_button dle-tool-btn dle-librarian-new-entry-btn" data-action="librarian-new" title="Create a new vault entry from scratch" data-i18n="[title]dle_new_entry_empty_tooltip">
<i class="fa-solid fa-plus" aria-hidden="true"></i> <span data-i18n="dle_librarian_new_entry_label">New Entry</span>
</button>
<button type="button" class="menu_button dle-tool-btn dle-librarian-vault-review-btn" data-action="librarian-review" title="AI-guided review of your vault" data-i18n="[title]dle_vault_review_tooltip">
<i class="fa-solid fa-wand-magic-sparkles" aria-hidden="true"></i> <span data-i18n="dle_librarian_vault_review_label">Vault Review</span>
</button>
</div>
</div>
<!-- ─── Tab: Tools ─── -->
<div class="dle-tab-panel" id="dle-panel-tools" data-tab="tools"
role="tabpanel" aria-labelledby="dle-tab-tools">
<div class="dle-tools-group">
<h3 class="dle-tools-group-label" data-i18n="dle_drawer_tools_inspect_heading">Inspect</h3>
<div class="dle-tools-grid">
<button type="button" class="menu_button dle-tool-btn" data-action="health" title="Run health check on all entries" data-i18n="[title]dle_health_check_tooltip">
<i class="fa-solid fa-heartbeat" aria-hidden="true"></i> <span data-i18n="dle_cmd_health_popup_title">Health Check</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="inspect" title="Inspect last lore selection — see what matched and why" data-i18n="[title]dle_drawer_tool_inspect_tooltip">
<i class="fa-solid fa-microscope" aria-hidden="true"></i> <span data-i18n="dle_drawer_tool_inspect_label">Inspect</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="status" title="Full system status" data-i18n="[title]dle_status_tooltip">
<i class="fa-solid fa-gauge-high" aria-hidden="true"></i> <span data-i18n="dle_status_button">Status</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="simulate" title="Simulate what entries would match" data-i18n="[title]dle_simulate_tooltip">
<i class="fa-solid fa-flask" aria-hidden="true"></i> <span data-i18n="dle_simulate_button">Simulate</span>
</button>
</div>
</div>
<div class="dle-tools-group">
<h3 class="dle-tools-group-label" data-i18n="dle_drawer_tools_notebooks_heading">Notebooks & History</h3>
<div class="dle-tools-grid">
<button type="button" class="menu_button dle-tool-btn" data-action="notebook" title="Author Notebook — persistent scratchpad for this chat" data-i18n="[title]dle_drawer_tool_notebook_tooltip">
<i class="fa-solid fa-book" aria-hidden="true"></i> <span data-i18n="dle_feature_author_notebook_h4">Author Notebook</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="ai-notebook" title="AI Notepad — session notes written by the AI via dle-notes tags" data-i18n="[title]dle_drawer_tool_ai_notepad_tooltip">
<i class="fa-solid fa-robot" aria-hidden="true"></i> <span data-i18n="dle_feature_ai_notepad_h4">AI Notepad</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="scribe-history" title="View Scribe history" data-i18n="[title]dle_scribe_history_tooltip">
<i class="fa-solid fa-clock-rotate-left" aria-hidden="true"></i> <span data-i18n="dle_scribe_history_button">Scribe History</span>
</button>
</div>
</div>
<div class="dle-tools-group">
<h3 class="dle-tools-group-label" data-i18n="dle_ai_utilities_label">AI Utilities</h3>
<div class="dle-tools-grid">
<button type="button" class="menu_button dle-tool-btn" data-action="ai-review" title="Review AI search decisions (/dle-review)" data-i18n="[title]dle_ai_review_tooltip">
<i class="fa-solid fa-magnifying-glass-chart" aria-hidden="true"></i> <span data-i18n="dle_ai_review_button">AI Review</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="summarize" title="Generate entry summaries via AI" data-i18n="[title]dle_summarize_tooltip">
<i class="fa-solid fa-wand-magic-sparkles" aria-hidden="true"></i> <span data-i18n="dle_summarize_button">Summarize</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="optimize-keys" title="Optimize entry keywords" data-i18n="[title]dle_optimize_keys_tooltip">
<i class="fa-solid fa-key" aria-hidden="true"></i> <span data-i18n="dle_tool_optimize_keys">Optimize Keys</span>
</button>
</div>
</div>
<div class="dle-tools-group">
<h3 class="dle-tools-group-label" data-i18n="dle_drawer_tools_vault_ops_heading">Vault Ops</h3>
<div class="dle-tools-grid">
<button type="button" class="menu_button dle-tool-btn" data-action="import-wi" title="Import World Info (lorebook) entries from SillyTavern to Obsidian" data-i18n="[title]dle_import_wi_tooltip">
<i class="fa-solid fa-file-import" aria-hidden="true"></i> <span data-i18n="dle_import_wi_button">Import World Info</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="graph" title="Visualize entry relationships" data-i18n="[title]dle_graph_tool_tooltip">
<i class="fa-solid fa-diagram-project" aria-hidden="true"></i> <span data-i18n="dle_feature_graph_h4">Graph</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="refresh" title="Refresh vault index from Obsidian" data-i18n="[title]dle_refresh_tool_tooltip">
<i class="fa-solid fa-arrows-rotate" aria-hidden="true"></i> <span data-i18n="dle_common_refresh">Refresh</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="pins-blocks" title="View pins and blocks for this chat" data-i18n="[title]dle_pins_blocks_tooltip">
<i class="fa-solid fa-thumbtack" aria-hidden="true"></i> <span data-i18n="dle_pins_blocks_button">Pins/Blocks</span>
</button>
</div>
</div>
<div class="dle-tools-group">
<h3 class="dle-tools-group-label" data-i18n="dle_drawer_tools_help_heading">Get Help</h3>
<div class="dle-tools-grid">
<button type="button" class="menu_button dle-tool-btn" data-action="setup" title="Guided setup wizard" data-i18n="[title]dle_drawer_tool_setup_wizard_tooltip">
<i class="fa-solid fa-hat-wizard" aria-hidden="true"></i> <span data-i18n="dle_drawer_tool_setup_wizard_label">Setup Wizard</span>
</button>
<button type="button" class="menu_button dle-tool-btn" data-action="help" title="Help and documentation" data-i18n="[title]dle_help_tooltip">
<i class="fa-solid fa-circle-info" aria-hidden="true"></i> <span data-i18n="dle_common_help">Help</span>
</button>
</div>
</div>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════════════════════
ZONE 3: Health Footer (always visible)
═══════════════════════════════════════════════════════════════════════════ -->
<div id="dle-drawer-footer" class="dle-drawer-zone dle-zone-footer" role="contentinfo" aria-label="DeepLore health and context">
<!-- Context window bar -->
<div class="dle-context-bar-container" role="progressbar" aria-valuenow="0" aria-valuemax="1" aria-valuemin="0"
aria-label="Context window: how much of the AI's memory is being used by your conversation, lore, and settings"
title="Context window: how much of the AI's memory is being used by your conversation, lore, and settings">
<div class="dle-context-bar-track">
<div class="dle-context-bar-context" title="Context tokens used"></div>
<div class="dle-context-bar-response" title="Response token reservation"></div>
<span class="dle-context-bar-label" data-i18n="dle_context_unavailable">Context data unavailable — waiting for first generation</span>
</div>
</div>
<!-- A2: real Librarian token I/O of the last agentic turn — a separate API call, NOT part
of the settled prompt window above. Hidden until a Librarian turn runs this chat. -->
<div class="dle-librarian-usage dle-hidden"></div>
<!-- Activity feed (recent pipeline runs) -->
<details class="dle-activity-feed-wrap">
<summary class="dle-activity-feed-toggle"><i class="fa-solid fa-list-timeline" aria-hidden="true"></i> <span data-i18n="dle_recent_activity_summary">Recent Activity</span></summary>
<div class="dle-activity-feed"></div>
</details>
<!-- Health icons + AI stats row -->
<div class="dle-footer-row">
<!-- f4-dock: the five health icons are a clickable "diagnostics dock" — each icon opens
its own diagnostic (handlers in drawer-events.js wireHealthIcons). The dock framing
(label + chrome) + per-icon affordance live in CSS; markup adds the dock label and a
hint caret so they no longer read as flat decoration. -->
<div class="dle-diag-dock">
<span class="dle-diag-dock-label dle-text-xs dle-muted" aria-hidden="true" data-i18n="dle_footer_diagnostics_label">Diagnostics</span>
<div class="dle-health-icons" role="toolbar" aria-label="System diagnostics — click an icon to open its check" data-i18n="[aria-label]dle_footer_diagnostics_dock_aria">
<button type="button" class="dle-health-icon" data-health="vault" title="Vault health — click to run health check" aria-label="Vault health: loading" data-i18n="[title]dle_vault_health_tooltip">
<i class="fa-solid fa-database" aria-hidden="true"></i>
</button>
<button type="button" class="dle-health-icon" data-health="connection" title="Obsidian connection status — click for full status" aria-label="Connection status: loading" data-i18n="[title]dle_connection_status_tooltip">
<i class="fa-solid fa-plug" aria-hidden="true"></i>
</button>
<button type="button" class="dle-health-icon" data-health="pipeline" title="Lore selection — click to inspect last trace" aria-label="Lore selection: loading" data-i18n="[title]dle_lore_selection_tooltip">
<i class="fa-solid fa-list-check" aria-hidden="true"></i>
</button>
<button type="button" class="dle-health-icon" data-health="cache" title="Index cache status — click for details" aria-label="Cache status: loading" data-i18n="[title]dle_cache_status_tooltip">
<i class="fa-solid fa-box-archive" aria-hidden="true"></i>
</button>
<button type="button" class="dle-health-icon" data-health="ai" title="AI search service status — click for details" aria-label="AI service status: loading" data-i18n="[title]dle_ai_service_status_tooltip">
<i class="fa-solid fa-robot" aria-hidden="true"></i>
</button>
<!-- PR #28.1: only visible when breaker open (renderFooter toggles dle-hidden). -->
<button type="button" id="dle-reset-ai-breaker" class="dle-health-icon dle-health-icon-action dle-hidden" title="Reset AI breaker — discard pending cooldown" aria-label="Reset AI circuit breaker" data-i18n="[title]dle_reset_ai_breaker_tooltip">
<i class="fa-solid fa-rotate-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="dle-ai-stats" aria-label="AI search session statistics — cumulative for this browser session, not per-chat" data-i18n="[aria-label]dle_drawer_ai_stats_aria">
<!-- D5 (v2.5 Wave 3): visible scope marker. These figures are session-cumulative
across ALL chats (reset on reload), NOT this chat — without the label they read
as "this chat" next to the per-chat health icons. Plain English literal (matches
the dynamically-rendered stat text, which is also non-i18n), so it adds no
all-locale parity churn. See docs/gotchas.md #75. -->
<span class="dle-ai-stats-scope" title="Session totals — cumulative across all chats this browser session (reset on reload), not the current chat">Session</span>
<span class="dle-ai-stat" data-ai-stat="calls" title="AI search calls made this browser session — resets when you reload" data-i18n="[title]dle_drawer_ai_stat_calls_tooltip">0 calls</span>
<span class="dle-ai-stat" data-ai-stat="cached" title="Times AI search reused previous results instead of calling the API" data-i18n="[title]dle_drawer_ai_stat_cached_tooltip">0 cached</span>
<span class="dle-ai-stat" data-ai-stat="tokens" title="Total tokens used by AI search this session" data-i18n="[title]dle_drawer_ai_stat_tokens_tooltip">0 tokens</span>
</div>
</div>
</div>
<!-- Screen reader announcements (visually hidden, announced via aria-live) -->
<div id="dle-drawer-live" class="dle-sr-only" aria-live="polite" aria-atomic="true"></div>