finch-markdown-editor 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/panel.css CHANGED
@@ -45,13 +45,20 @@ body{margin:0;background:var(--bg);color:var(--text);font:13px var(--finch-font-
45
45
  .home-btn svg{width:14px;height:14px;flex:none}
46
46
  .home-section{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin:0 0 10px;font-size:12px;color:var(--muted)}
47
47
  .home-section b{font-size:12.5px;font-weight:600;color:var(--text);flex:none}
48
+ /* Wrapper for the recent-documents area: a plain flex column of `.home-group`
49
+ blocks (one per Space/workspace/other, same grouping+order as the Library
50
+ drawer). Every block gets its own header row + a divider above it. */
51
+ .home-groups{display:flex;flex-direction:column;gap:18px}
52
+ .home-group-title{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 10px;padding-top:14px;border-top:1px solid var(--border);font-size:11.5px;font-weight:600;color:var(--muted)}
53
+ .home-group-label{display:flex;align-items:baseline;gap:6px;min-width:0;flex:0 1 auto}
54
+ .home-group-count{font-weight:400;opacity:.7;flex:none}
48
55
  /* flex:0 1 auto (not flex:1) so the button hugs its own text — the blank
49
56
  space next to a short path stays unclickable. Front-truncation (the "…"
50
57
  prefix) happens in JS, not via a direction:rtl CSS trick: mixing a plain
51
58
  "~" with rtl reordered the whole string visually ("finch-tools/~" instead
52
59
  of "~/finch-tools"), so this box now renders left-to-right like normal. */
53
- .home-section .home-cwd{flex:0 1 auto;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.75;cursor:pointer;background:none;border:0;padding:0;font:inherit;color:inherit}
54
- .home-section .home-cwd:hover{opacity:1;color:var(--accent);text-decoration:underline}
60
+ .home-group-cwd{flex:0 1 auto;max-width:55%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.75;cursor:pointer;background:none;border:0;padding:0;font:inherit;font-weight:400;color:inherit}
61
+ .home-group-cwd:hover{opacity:1;color:var(--accent);text-decoration:underline}
55
62
  .home-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:12px}
56
63
  .doc-card{position:relative;display:flex;flex-direction:column;height:138px;padding:0;text-align:left;border:1px solid var(--border);border-radius:11px;background:var(--bg);color:var(--text);font:inherit;cursor:pointer;overflow:hidden;transition:border-color .15s ease,box-shadow .15s ease,transform .1s ease}
57
64
  .doc-card:hover{border-color:var(--accent);box-shadow:0 5px 16px rgba(0,0,0,.1)}
@@ -79,6 +86,13 @@ body{margin:0;background:var(--bg);color:var(--text);font:13px var(--finch-font-
79
86
  .status{font-size:12px;color:var(--muted);padding:5px 10px;text-align:center;border-top:1px solid var(--border);background:var(--bg)}
80
87
  .status a{color:var(--accent);text-decoration:underline;text-underline-offset:2px;cursor:pointer}
81
88
  .status.error{color:#c54232}
89
+ .status-inline-btn{margin-left:6px;padding:1px 8px;border:1px solid var(--border);border-radius:20px;background:var(--card);color:var(--accent);font:inherit;font-size:11px;line-height:1.6;cursor:pointer}
90
+ .status-inline-btn:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
91
+ /* App View keeps this pill plain/active text instead of the accent
92
+ treatment used elsewhere — it's a routine "save" action here, not
93
+ something that needs to compete visually with the rest of the chrome. */
94
+ body.app-view .status-inline-btn{color:var(--text)}
95
+ body.app-view .status-inline-btn:hover{background:var(--finch-bg-hover,var(--bg));color:var(--text);border-color:var(--border)}
82
96
  .status:empty{padding:0;border-top:0}
83
97
  /* Changed glyphs briefly take the accent color, then settle back to normal
84
98
  text. Nested syntax spans receive the same animation; no background flash. */
@@ -167,10 +181,17 @@ body{margin:0;background:var(--bg);color:var(--text);font:13px var(--finch-font-
167
181
  body.app-view .app-toolbar{display:flex!important}
168
182
  .app-toolbar-group{display:flex;align-items:center;gap:6px;flex:none}
169
183
  .app-toolbar-end{margin-left:auto}
170
- .app-tool{height:32px;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text);font:12px var(--finch-font-body,system-ui);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;min-width:32px;padding:0 8px;gap:6px}
171
- .app-tool svg{width:19px;height:19px;stroke-width:1.8}.app-tool:hover:not(:disabled){background:var(--finch-bg-hover,var(--bg))}
172
- .app-tool:disabled{opacity:.4;cursor:default}.app-tool.checked{color:var(--text);background:var(--finch-bg-active,color-mix(in srgb,var(--text) 10%,transparent))}.app-tool.dirty{color:var(--accent);background:transparent}
173
- .app-tool-label{min-width:auto;padding:0 9px}.app-menu-wrap{position:relative}.app-menu{position:absolute;z-index:32;top:calc(100% + 7px);right:0;min-width:174px;padding:5px;border:1px solid var(--border);border-radius:9px;background:var(--card);box-shadow:0 2px 8px rgba(0,0,0,.12)}
184
+ .app-toolbar-sep{width:1px;height:20px;margin:0 2px;background:var(--border);flex:none}
185
+ .app-tool{height:32px;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text);font:14px var(--finch-font-body,system-ui);font-weight:500;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;min-width:32px;padding:0 8px;gap:6px;line-height:0}
186
+ /* `display:block` takes every toolbar icon out of inline/baseline layout —
187
+ without it, a bare <svg> button (home/library/open) and an icon wrapped
188
+ in a <span> (save) end up centered by two different rules (flex-item
189
+ blockification vs. the span's own line-height baseline) and visibly
190
+ drift a couple of px apart even though both parents are
191
+ align-items:center flex boxes. */
192
+ .app-tool svg{display:block;width:17px;height:17px;stroke-width:1.8}.app-tool:hover:not(:disabled){background:var(--finch-bg-hover,var(--bg))}
193
+ .app-tool:disabled{opacity:.4;cursor:default}.app-tool.checked{color:var(--text);background:var(--finch-bg-active,color-mix(in srgb,var(--text) 10%,transparent))}.app-tool.dirty{background:transparent}
194
+ .app-tool-label{min-width:auto;padding:0 9px}.ic-save,.ic-save-check{display:inline-flex;align-items:center}.ic-save[hidden],.ic-save-check[hidden]{display:none}.app-menu-wrap{position:relative}.app-menu{position:absolute;z-index:32;top:calc(100% + 7px);right:0;min-width:174px;padding:5px;border:1px solid var(--border);border-radius:9px;background:var(--card);box-shadow:0 2px 8px rgba(0,0,0,.12)}
174
195
  .app-menu button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:12px;padding:7px 9px;border:0;border-radius:6px;background:transparent;color:var(--text);font:12px var(--finch-font-body,system-ui);text-align:left;cursor:pointer}.app-menu button:hover{background:var(--finch-bg-hover,var(--bg))}.app-menu button.checked{color:var(--text);background:var(--finch-bg-active,color-mix(in srgb,var(--text) 10%,transparent));font-weight:600}.app-menu hr{margin:5px 3px;border:0;border-top:1px solid var(--border)}
175
196
  .app-document-meta{min-width:0;display:flex;flex-direction:column;gap:1px}.app-document-meta strong,.app-document-meta span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-document-meta strong{font-size:13px}.app-document-meta span{max-width:34vw;color:var(--muted);font-size:11px}
176
197
  body.app-view .stage{display:grid;grid-template-columns:minmax(0,1fr) 6px var(--preview-width,480px);background:var(--bg)}
@@ -182,6 +203,16 @@ body.app-view .preview-shell{padding:20px;display:flex;justify-content:center;al
182
203
  body.app-view #article{width:100%;border:1px solid var(--border)}
183
204
  body.app-view.preview-hidden .stage{grid-template-columns:minmax(0,1fr)}body.app-view.preview-hidden #previewPane,body.app-view.preview-hidden .preview-resizer{display:none!important}
184
205
  @keyframes cm-ai-spin{to{transform:rotate(360deg)}}
206
+ .ic-ai-style-loading{animation:cm-ai-spin .8s linear infinite}
207
+ .ic-ai-style[hidden],.ic-ai-style-loading[hidden]{display:none}
208
+ /* App View has no Composer to turn "let AI design a layout" into a normal
209
+ conversation the user can steer — it only had a fire-and-forget Session
210
+ with no back-and-forth, which was a worse experience than doing this from
211
+ the sidebar panel where the user can chat with AI about the style directly.
212
+ Hide the entry point (and its leading separator) here; the sidebar panel
213
+ keeps the full flow. */
214
+ body.app-view #actAiStyle{display:none!important}
215
+ body.app-view .actions .sep:has(+ #actAiStyle){display:none!important}
185
216
  .preview-resizer{position:relative;z-index:10;width:6px;cursor:col-resize;background:var(--border);opacity:0;transition:opacity .15s ease}.preview-resizer:hover,.preview-resizer.active{opacity:1}
186
217
  .app-tool{position:relative}.app-tool[data-tooltip]::after{content:attr(data-tooltip);position:absolute;left:50%;top:calc(100% + 8px);z-index:40;padding:6px 8px;border:1px solid var(--border);border-radius:7px;background:var(--card);box-shadow:0 5px 16px rgba(0,0,0,.2);color:var(--text);font-size:12px;line-height:1;white-space:nowrap;pointer-events:none;opacity:0;transform:translate(-50%,-3px);transition:opacity .16s ease,transform .16s ease}.app-tool[data-tooltip]:hover::after{opacity:1;transform:translate(-50%,0)}
187
218
  body.app-view .empty{grid-column:1/-1;background:var(--bg);padding:54px 38px}
@@ -190,7 +221,28 @@ body.app-view .actions{right:28px;bottom:28px}
190
221
  .library-backdrop{position:fixed;z-index:39;inset:0;background:rgba(0,0,0,.24)}
191
222
  .library-drawer{position:fixed;z-index:40;top:0;bottom:0;left:0;width:min(390px,88vw);padding:0;background:var(--card);border-right:1px solid var(--border);transform:translateX(-102%);transition:transform .18s ease;display:flex;flex-direction:column}
192
223
  .library-drawer.open{transform:translateX(0)}.library-drawer>header{height:58px;display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--border)}
193
- .library-drawer>header div{display:flex;flex-direction:column}.library-drawer>header span{font-size:11px;color:var(--muted)}.library-drawer>header button{border:0;background:transparent;color:var(--muted);font-size:24px;cursor:pointer}
224
+ .library-drawer>header div{display:flex;flex-direction:column}.library-drawer>header span{font-size:11px;color:var(--muted)}.library-drawer>header>button{border:0;background:transparent;color:var(--muted);font-size:24px;cursor:pointer}
225
+ /* Specificity note: `.library-drawer>header div` above sets
226
+ flex-direction:column for every plain <div> in the header (the title
227
+ block wants that). This selector must out-specificity it, or the two
228
+ buttons here stack vertically instead of sitting side by side. */
229
+ .library-drawer>header .library-header-actions{display:flex;flex-direction:row;align-items:center;gap:2px}
230
+ .library-icon-btn{border:0;background:transparent;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:7px;padding:0}
231
+ .library-icon-btn svg{width:16px;height:16px}
232
+ .library-icon-btn:hover{background:var(--finch-bg-hover,var(--bg));color:var(--text)}
233
+ .library-icon-btn.active{background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent)}
234
+ .library-header-actions #libraryClose{border:0;background:transparent;color:var(--muted);font-size:24px;cursor:pointer;line-height:1;width:28px;height:28px;border-radius:7px}
235
+ .library-header-actions #libraryClose:hover{background:var(--finch-bg-hover,var(--bg));color:var(--text)}
236
+ /* Reorder mode: groups collapse to flat draggable header rows (no expand/
237
+ collapse, no per-document rows) so ordering is the only thing to do. */
238
+ .library-group-reorder{display:flex;align-items:center;gap:8px;min-height:38px;padding:0 9px;border-radius:9px;cursor:grab;user-select:none;touch-action:none}
239
+ .library-group-reorder:hover{background:var(--finch-bg-hover,var(--bg))}
240
+ .library-group-reorder.dragging{opacity:.32}
241
+ .library-group-reorder[data-draggable]:not([data-draggable="true"]),.library-group-reorder:not([data-draggable]){cursor:default;opacity:.7}
242
+ .library-reorder-handle{flex:none;width:14px;text-align:center;color:var(--muted);font-size:13px;line-height:1;letter-spacing:-1px}
243
+ .library-reorder-footer{flex:none;padding:10px 14px;border-top:1px solid var(--border)}
244
+ .library-reorder-footer button{width:100%;border:0;border-radius:8px;background:var(--accent);color:#fff;font:inherit;font-size:13px;font-weight:600;padding:9px 0;cursor:pointer}
245
+ .library-reorder-footer button:hover{filter:brightness(1.05)}
194
246
  /* Directory-like library: every source group is a native collapsible
195
247
  details/summary, while rows separate a readable title from the quieter
196
248
  path + time metadata instead of cramming all three into one text run. */
@@ -204,4 +256,8 @@ body.app-view .actions{right:28px;bottom:28px}
204
256
  .library-drag-ghost{position:fixed;left:0;top:0;z-index:9999;pointer-events:none;margin:0;border-radius:10px;background:var(--card,var(--bg));box-shadow:0 10px 28px color-mix(in srgb,#000 22%,transparent),0 2px 6px color-mix(in srgb,#000 12%,transparent);transform:scale(1.02) rotate(-1deg);opacity:.96;overflow:hidden}
205
257
  .library-drag-ghost .library-items{display:none}.library-drag-ghost summary{cursor:grabbing}
206
258
  .library-row{display:block;width:100%;padding:9px 9px 8px;border:0;border-radius:7px;background:transparent;color:var(--text);text-align:left;cursor:pointer}.library-row:hover{background:var(--finch-bg-hover,var(--bg))}.library-row-main,.library-row strong,.library-row-meta,.library-row-path{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.library-row strong{font-size:13px;line-height:1.35;font-weight:600}.library-row-meta{display:flex;align-items:center;gap:7px;margin-top:3px;color:var(--muted);font-size:11px;line-height:1.3}.library-row-path,.library-row time{color:var(--muted)}.library-row-path{flex:1}.library-row time{flex:none;opacity:.86}
207
- @media(max-width:850px){body.app-view .stage{grid-template-columns:minmax(0,1fr) 6px min(var(--preview-width,480px),40vw)}.app-document-meta span{display:none}.app-toolbar{gap:6px}.app-tool-label{padding:0 8px}}
259
+ @media(max-width:850px){body.app-view .stage{grid-template-columns:minmax(0,1fr) 6px min(var(--preview-width,480px),40vw)}.app-toolbar{gap:6px}.app-tool-label{padding:0 8px}}
260
+ /* Keep the App View toolbar usable when the Finch window is narrow. Icon-only
261
+ buttons retain their localized tooltip/aria label; only the two redundant
262
+ visible labels collapse, so no action is pushed off-screen. */
263
+ @media(max-width:680px){.app-toolbar{gap:4px;padding-inline:8px}.app-toolbar-group{gap:2px}.app-toolbar-end{min-width:0}.app-tool{min-width:30px;padding-inline:6px}.app-tool-label{min-width:30px;padding-inline:7px}.app-tool-label>span[data-i18n]{display:none}}
package/dist/panel.html CHANGED
@@ -11,15 +11,16 @@
11
11
  <main class="app">
12
12
  <header id="appToolbar" class="app-toolbar" hidden>
13
13
  <div class="app-toolbar-group">
14
- <button id="appHome" class="app-tool" type="button" data-i18n-tooltip="toolbar.home.tooltip" aria-label="Home"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg></button>
15
14
  <button id="appLibrary" class="app-tool" type="button" data-i18n-tooltip="appview.library" aria-label="Library"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/><path d="m14 9 3 3-3 3"/></svg></button>
15
+ <span class="app-toolbar-sep" aria-hidden="true"></span>
16
+ <button id="appHome" class="app-tool" type="button" data-i18n-tooltip="toolbar.home.tooltip" aria-label="Home"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg></button>
16
17
  <button id="appOpen" class="app-tool" type="button" data-i18n-tooltip="home.openFile" aria-label="Open File"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"/></svg></button>
17
18
  <button id="appSave" class="app-tool app-tool-label" type="button" data-i18n-tooltip="toolbar.save.tooltipDefault"><span class="ic-save"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"/><path d="M7 3v4a1 1 0 0 0 1 1h7"/></svg></span><span class="ic-save-check" hidden><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.5 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h10.2a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4v4.35"/><path d="m16 19 2 2 4-4"/><path d="M17 15.13V14a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"/><path d="M7 3v4a1 1 0 0 0 1 1h7"/></svg></span><span data-i18n="toolbar.save.label">Save</span></button>
18
19
  </div>
19
- <div class="app-document-meta"><strong id="appDocumentTitle" data-i18n="home.title">Writing</strong><span id="appDocumentPath"></span></div>
20
20
  <div class="app-toolbar-group app-toolbar-end">
21
- <button id="appPreview" class="app-tool app-tool-label checked" type="button" data-i18n-tooltip="toolbar.mode.label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/></svg><span data-i18n="toolbar.mode.label">Preview</span></button>
22
- <div class="app-menu-wrap"><button id="appStyle" class="app-tool" type="button" data-i18n-tooltip="toolbar.style.tooltip"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"/><path d="M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"/><path d="M 7 17h.01"/><path d="m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"/></svg></button><div id="appStyleMenu" class="app-menu" hidden></div></div>
21
+ <button id="appPreview" class="app-tool app-tool-label checked" type="button" data-i18n-tooltip="toolbar.mode.label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"/><path d="M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"/><path d="M 7 17h.01"/><path d="m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"/></svg><span data-i18n="toolbar.mode.label">Preview</span></button>
22
+ <div class="app-menu-wrap"><button id="appStyle" class="app-tool" type="button" data-i18n-tooltip="toolbar.style.tooltip"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z"/><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/></svg></button><div id="appStyleMenu" class="app-menu" hidden></div></div>
23
+ <span class="app-toolbar-sep" aria-hidden="true"></span>
23
24
  <button id="appFocus" class="app-tool" type="button" data-i18n-tooltip="appview.focus"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.086 18.412A2 2 0 0 1 12.67 19H5v-7.672a2 2 0 0 1 .586-1.414L11.75 3.75a6 6 0 1 1 8.49 8.49z"/><path d="M16 8 2 22"/><path d="M17.488 15H9"/></svg></button>
24
25
  <div class="app-menu-wrap"><button id="appFont" class="app-tool" type="button" data-i18n-tooltip="toolbar.fontSize.tooltipEdit"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v16"/><path d="M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2"/><path d="M9 20h6"/></svg></button><div id="appFontMenu" class="app-menu" hidden></div></div>
25
26
  <div class="app-menu-wrap"><button id="appMore" class="app-tool" type="button" data-i18n-tooltip="toolbar.more.tooltip"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg></button><div id="appMoreMenu" class="app-menu" hidden></div></div>
@@ -45,8 +46,8 @@
45
46
  </div>
46
47
  </header>
47
48
  <section id="homeRecent" class="home-recent" hidden>
48
- <div class="home-section"><b data-i18n="home.recentLabel">Recent</b><button id="homeCwd" type="button" class="home-cwd"></button></div>
49
- <div id="homeGrid" class="home-grid"></div>
49
+ <div class="home-section"><b data-i18n="home.recentLabel">Recent</b></div>
50
+ <div id="homeGrid" class="home-groups"></div>
50
51
  </section>
51
52
  <p id="homeHint" class="home-hint" data-i18n="home.hintDefault">Open a Markdown file — recently edited documents will show up here.</p>
52
53
  </div>
@@ -76,7 +77,8 @@
76
77
  </button>
77
78
  <span class="sep" data-collapsible></span>
78
79
  <button id="actAiStyle" type="button" data-i18n-tooltip="actions.aiStyle" aria-label="Ask AI to design layout" data-collapsible>
79
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72"/><path d="m14 7 3 3"/><path d="M5 6v4"/><path d="M19 14v4"/><path d="M10 2v2"/><path d="M7 8H3"/><path d="M21 16h-4"/><path d="M11 3H9"/></svg>
80
+ <svg class="ic-ai-style" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72"/><path d="m14 7 3 3"/><path d="M5 6v4"/><path d="M19 14v4"/><path d="M10 2v2"/><path d="M7 8H3"/><path d="M21 16h-4"/><path d="M11 3H9"/></svg>
81
+ <svg class="ic-ai-style-loading" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" hidden><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
80
82
  </button>
81
83
  <button id="actToggle" type="button" class="act-toggle" data-i18n-tooltip="actions.toggle" aria-label="Expand/collapse">
82
84
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
@@ -88,8 +90,18 @@
88
90
  <div id="status" class="status"></div>
89
91
  <div id="libraryBackdrop" class="library-backdrop" hidden></div>
90
92
  <aside id="libraryDrawer" class="library-drawer" aria-hidden="true">
91
- <header><div><strong data-i18n="appview.library">Library</strong><span data-i18n="appview.libraryHint">Recent documents across Spaces</span></div><button id="libraryClose" type="button" aria-label="Close">×</button></header>
93
+ <header><div><strong data-i18n="appview.library">Library</strong><span data-i18n="appview.libraryHint">Recent documents across Spaces</span></div>
94
+ <div class="library-header-actions">
95
+ <button id="libraryReorder" type="button" class="library-icon-btn" aria-label="Reorder" data-i18n-aria="appview.libraryReorder" data-i18n-tooltip="appview.libraryReorder">
96
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>
97
+ </button>
98
+ <button id="libraryClose" type="button" aria-label="Close">×</button>
99
+ </div>
100
+ </header>
92
101
  <div id="libraryGroups" class="library-groups"></div>
102
+ <div id="libraryReorderFooter" class="library-reorder-footer" hidden>
103
+ <button id="libraryReorderDone" type="button" data-i18n="appview.libraryReorderDone">Done</button>
104
+ </div>
93
105
  </aside>
94
106
  </main>
95
107
  <section id="popup" class="popup hidden">