pi-weave 0.3.0 → 0.3.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/README.md +40 -16
- package/package.json +2 -2
- package/src/core/frontmatter.ts +3 -3
- package/src/core/graph/model.ts +2 -2
- package/src/core/graph/wikilinks.ts +1 -1
- package/src/core/types.ts +1 -1
- package/src/pi/viewer/tui/surface/detail.ts +1 -1
- package/src/web/client/dist/app.js +239 -243
- package/src/web/client/graph/ForceTuner.tsx +14 -98
- package/src/web/client/graph/Graph.tsx +29 -74
- package/src/web/client/graph/column.model.ts +22 -15
- package/src/web/client/graph/graph.model.ts +31 -63
- package/src/web/client/graph/groups.ts +9 -7
- package/src/web/client/graph/positions.ts +3 -3
- package/src/web/client/graph/renderer.dom.ts +2 -2
- package/src/web/client/graph/renderer.ts +14 -5
- package/src/web/client/graph/tuner.model.ts +6 -180
- package/src/web/client/main.tsx +1 -4
- package/src/web/client/note/Note.tsx +77 -92
- package/src/web/client/note/drafts.ts +172 -0
- package/src/web/client/note/note.model.ts +2 -34
- package/src/web/client/search/SearchPalette.tsx +9 -8
- package/src/web/client/shell/ContextRail.tsx +8 -9
- package/src/web/client/shell/Settings.tsx +71 -0
- package/src/web/client/shell/Shell.tsx +409 -255
- package/src/web/client/shell/StatusBar.tsx +2 -6
- package/src/web/client/shell/focus.model.ts +2 -2
- package/src/web/client/shell/keys.model.ts +40 -39
- package/src/web/client/shell/keys.ts +1 -0
- package/src/web/client/shell/shell.model.ts +32 -128
- package/src/web/client/shell/theme.model.ts +27 -97
- package/src/web/client/shell/theme.ts +32 -238
- package/src/web/client/shell/workspace.css.ts +140 -0
- package/src/web/client/tree/Tree.tsx +43 -14
- package/src/web/client/tree/tree.model.ts +19 -0
- package/src/web/client/workspace.ts +19 -1
- package/src/web/server/backup.ts +59 -0
- package/src/web/server/routes.ts +45 -3
- package/src/web/server/server.ts +5 -0
- package/src/web/server/workspace-state.ts +121 -0
- package/src/web/shared/layout.ts +5 -6
- package/src/web/shared/preferences.ts +76 -0
- package/src/web/shared/themes.ts +92 -0
- package/src/web/shared/workspace.ts +310 -0
- package/src/web/client/selection.storage.ts +0 -69
- package/src/web/client/shell/Columns.tsx +0 -139
- package/src/web/client/shell/Divider.tsx +0 -15
- package/src/web/client/shell/Header.tsx +0 -119
- package/src/web/client/shell/drag.model.ts +0 -35
- package/src/web/client/shell/layout.model.ts +0 -132
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { THEMES, ACCENTS } from "../../shared/themes";
|
|
2
|
+
import type { PaletteChoice } from "../../shared/themes";
|
|
3
|
+
import { WORKSPACE_CSS } from "./workspace.css";
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* The workspace stylesheet, and how it gets past the CSP
|
|
3
7
|
* (weave-workspace §1.2, §5.2).
|
|
@@ -43,96 +47,19 @@
|
|
|
43
47
|
* real `document` satisfies it structurally.
|
|
44
48
|
*/
|
|
45
49
|
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* here.
|
|
56
|
-
*
|
|
57
|
-
* And since `shell/theme.model.ts`, the palette a user looks at is a
|
|
58
|
-
* *choice*: `:root` carries dark, the light tokens sit in
|
|
59
|
-
* {@link LIGHT_TOKENS} and are applied by a `data-weave-theme` attribute
|
|
60
|
-
* (a manual selection) and by the media query narrowed with
|
|
61
|
-
* `:root:not([data-weave-theme="dark"])` (the system default). Clearing the
|
|
62
|
-
* attribute returns the workspace to following the OS with no client-side
|
|
63
|
-
* listener involved. The graph follows the same resolution through
|
|
64
|
-
* `theme.model.ts`'s `effectiveScheme`, because its WebGL palette cannot
|
|
65
|
-
* read any of this.
|
|
66
|
-
*
|
|
67
|
-
* ## "Dense but calm" (§1.2)
|
|
68
|
-
*
|
|
69
|
-
* The sketch is an information-dense IDE surface, not a marketing page, so
|
|
70
|
-
* the rules below deliberately avoid the defaults that produce the opposite:
|
|
71
|
-
* no card shadows, no 24 px gutters, no rounded panels floating on a
|
|
72
|
-
* contrasting background. Density comes from a 13 px base, 4–10 px padding
|
|
73
|
-
* and 1 px hairline rules; calm comes from a **single** accent colour used
|
|
74
|
-
* only for focus and selection, three greys doing all the structural work,
|
|
75
|
-
* and no borders where a background change already separates two regions.
|
|
76
|
-
*
|
|
77
|
-
* ## Where the hexes come from
|
|
78
|
-
*
|
|
79
|
-
* Both schemes are Catppuccin (the user's call): dark is **Macchiato**, light
|
|
80
|
-
* is **Latte**, mapped onto the desk-and-page split with one structural rule
|
|
81
|
-
* shared by both — the note page is the `crust` ground, rails and bars are
|
|
82
|
-
* `mantle`, the desk and graph canvas are `base`, raised controls and
|
|
83
|
-
* hairlines are `surface0` with `surface1` for the strong hairline. Light's
|
|
84
|
-
* topology is therefore an exact mirror of dark's (a darker sheet on a lighter
|
|
85
|
-
* desk), so a token means the same thing in either scheme:
|
|
86
|
-
*
|
|
87
|
-
* - **Dark, Macchiato** — every value a stock Catppuccin label: `base #24273A`
|
|
88
|
-
* desk, `mantle #1E2030` panel, `crust #181926` page, `surface0 #363A4F`
|
|
89
|
-
* raise/hairline, `surface1 #494D64` strong hairline; text `#CAD3F5`,
|
|
90
|
-
* dims `#A5ADCB`/`#939AB7`, and **Mauve `#C6A0F6` as the single accent
|
|
91
|
-
* voice** (7.5:1 on panel) with Green/Yellow/Red as status.
|
|
92
|
-
*
|
|
93
|
-
* - **Light, Latte** — grounds are stock labels again (`base #EFF1F5` desk,
|
|
94
|
-
* `mantle #E6E9EF` panel, `crust #DCE0E8` page, `surface0 #CCD0DA`,
|
|
95
|
-
* `surface1 #BCC0CC`), and text/status hue-preservingly *deepened* to hold
|
|
96
|
-
* 4.5:1 on the darkest grounds Latte owns: `dim #56586A` (from Subtext0,
|
|
97
|
-
* same hue 233°), `faint #606274` (Overlay2), `accent #7113EC` (Mauve),
|
|
98
|
-
* `ok #28641B`, `warn #7C4F10`, `bad #B20D30`. Text `#4C4F69` is stock
|
|
99
|
-
* Text. The hue-preserving deepening keeps the palette recognisably
|
|
100
|
-
* Catppuccin where blending toward neutral would grey it away.
|
|
101
|
-
*
|
|
102
|
-
* Measured ratios (WCAG, on the darkest grounds — `raise`/`surface0` for
|
|
103
|
-
* light text tokens, `panel`/`mantle` for dark): light fg 4.5, dim 4.5,
|
|
104
|
-
* accent 4.5, ok 4.6, warn 4.6, bad 4.5, each also ≥ 4.5 on the brighter
|
|
105
|
-
* grounds; dark faint 4.6 on `surface0` and 5.8 on panel, dim 5.0 on
|
|
106
|
-
* `surface0`, fg 7.6. The one below-4.5 site is `faint` *on* `raise`
|
|
107
|
-
* (light 3.9) — every use is non-text there (scrollbar thumb, ghost
|
|
108
|
-
* borders, icon glyphs), where WCAG asks 3:1.
|
|
109
|
-
*
|
|
110
|
-
* Status colours keep each scheme's temperature at ≥ 4.5:1 text contrast —
|
|
111
|
-
* measured, not eyeballed (dark `#a6da95`/`#1e2030` 10.0, `#eed49f` 11.2,
|
|
112
|
-
* `#ed8796` 6.5; light values are the deepened derivatives above).
|
|
113
|
-
*
|
|
114
|
-
* The graph cannot read these variables (WebGL — `graph.model.ts`), so
|
|
115
|
-
* `GRAPH_PALETTE` mirrors the eight palette slots as literals; the test that makes
|
|
116
|
-
* that copy safe asserts every mirrored hex appears in this string.
|
|
117
|
-
*/
|
|
118
|
-
/**
|
|
119
|
-
* The light-block tokens, interpolated into both selectors that need them —
|
|
120
|
-
* see the {@link THEME_CSS} branch rules.
|
|
121
|
-
*/
|
|
122
|
-
const LIGHT_TOKENS = `
|
|
123
|
-
--weave-bg:#eff1f5;--weave-panel:#e6e9ef;--weave-raise:#ccd0da;--weave-fg:#4c4f69;--weave-dim:#56586a;
|
|
124
|
-
--weave-faint:#606274;--weave-line:#ccd0da;--weave-line-strong:#bcc0cc;
|
|
125
|
-
--weave-accent:#7113ec;--weave-ok:#28641b;--weave-warn:#7c4f10;--weave-bad:#b20d30;
|
|
126
|
-
--weave-new:rgba(113,19,236,.10);
|
|
127
|
-
--weave-page:#dce0e8;
|
|
128
|
-
`;
|
|
50
|
+
/** Palette declarations are shared with the WebGL graph. */
|
|
51
|
+
function paletteTokens(id: PaletteChoice): string {
|
|
52
|
+
const { scheme, colors } = THEMES[id];
|
|
53
|
+
return Object.entries(colors).map(([key, value]) => `--weave-${key}:${value};`).join("")
|
|
54
|
+
+ `--weave-new:color-mix(in srgb,var(--weave-accent) ${scheme === "light" ? 10 : 16}%,transparent);`
|
|
55
|
+
+ `color-scheme:${scheme};`
|
|
56
|
+
+ `--weave-vignette:radial-gradient(ellipse at center,transparent 55%,${scheme === "light" ? "rgba(0,0,0,.10)" : "rgba(0,0,0,.22)"} 100%);`
|
|
57
|
+
+ `--weave-scrim:rgba(0,0,0,${scheme === "light" ? ".30" : ".45"});`;
|
|
58
|
+
}
|
|
129
59
|
|
|
130
60
|
export const THEME_CSS = `
|
|
131
61
|
:root{
|
|
132
|
-
|
|
133
|
-
--weave-faint:#939ab7;--weave-line:#363a4f;--weave-line-strong:#494d64;
|
|
134
|
-
--weave-accent:#c6a0f6;--weave-ok:#a6da95;--weave-warn:#eed49f;--weave-bad:#ed8796;
|
|
135
|
-
--weave-new:rgba(198,160,246,.16);
|
|
62
|
+
${paletteTokens("dark")}
|
|
136
63
|
--weave-row:26px;--weave-gutter:10px;
|
|
137
64
|
/* The reading gutter is note-only: prose wants a wider margin than chrome.
|
|
138
65
|
Rails, rows and bars keep --weave-gutter, so density is a property of the
|
|
@@ -146,7 +73,7 @@ export const THEME_CSS = `
|
|
|
146
73
|
third face was tried (serif prose) and withdrawn at the user's call; two
|
|
147
74
|
voices read calmer than three. The CSP allows nothing fetched, and both
|
|
148
75
|
are system stacks. */
|
|
149
|
-
|
|
76
|
+
|
|
150
77
|
/* Two radii, per the plan: hairline-sharp for controls (a 4 px corner is
|
|
151
78
|
the difference between a control and a card), one softer corner for the
|
|
152
79
|
two overlays that float above the grid. Tag pills are 999px — a capsule
|
|
@@ -162,7 +89,7 @@ export const THEME_CSS = `
|
|
|
162
89
|
row 12 list rows, text inputs, inline code
|
|
163
90
|
base 13 body copy, h3-h6, preview-card text
|
|
164
91
|
body 13.5 the note column's prose
|
|
165
|
-
subhead 14 palette input, note-body h2,
|
|
92
|
+
subhead 14 palette input, note-body h2, ribbon icon buttons
|
|
166
93
|
title 15 note-body h1
|
|
167
94
|
display 20 the note's page title
|
|
168
95
|
Two earlier sizes were merged into neighbours: 9px glyphs to prov, and
|
|
@@ -181,101 +108,15 @@ export const THEME_CSS = `
|
|
|
181
108
|
--weave-px-row:12px;--weave-px-base:13px;--weave-px-body:13.5px;
|
|
182
109
|
--weave-px-subhead:14px;--weave-px-title:15px;--weave-px-display:20px;
|
|
183
110
|
}
|
|
184
|
-
/* The light tokens, shared verbatim by the attribute branch and the media
|
|
185
|
-
query below — one const interpolated twice is the only way CSS gets
|
|
186
|
-
"these are the same colours" without a preprocessor. Which branch wins is
|
|
187
|
-
theme.model.ts's business: the attribute carries a *manual* choice, the
|
|
188
|
-
media query the system default, and the :not() is what lets the two coexist
|
|
189
|
-
without a manual "dark" being dragged back into light by the OS. */
|
|
190
111
|
@media (prefers-color-scheme: light){
|
|
191
|
-
:root:not([data-weave-theme
|
|
192
|
-
${LIGHT_TOKENS}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
:root[data-weave-theme="light"]{
|
|
196
|
-
${LIGHT_TOKENS}
|
|
112
|
+
:root:not([data-weave-theme]){${paletteTokens("light")}}
|
|
197
113
|
}
|
|
114
|
+
${(Object.keys(THEMES) as PaletteChoice[]).map((id) => `:root[data-weave-theme="${id}"]{${paletteTokens(id)}}`).join("\n")}
|
|
115
|
+
${Object.entries(ACCENTS).map(([id, colors]) => ["light", "dark"].map((scheme) =>
|
|
116
|
+
`:root[data-weave-scheme="${scheme}"][data-weave-accent="${id}"]{--weave-accent:${colors[scheme as "light" | "dark"]};}`
|
|
117
|
+
).join("\n")).join("\n")}
|
|
198
118
|
body{font-size:var(--weave-px-base)}
|
|
199
|
-
#app{height:100%;display:grid;grid-template-rows:
|
|
200
|
-
|
|
201
|
-
/* header --------------------------------------------------------------- */
|
|
202
|
-
.weave-header{
|
|
203
|
-
display:flex;align-items:center;gap:14px;padding:0 var(--weave-gutter);
|
|
204
|
-
height:34px;border-bottom:1px solid var(--weave-line);background:var(--weave-panel);
|
|
205
|
-
}
|
|
206
|
-
.weave-brand{display:inline-flex;align-items:center;gap:6px;font-size:var(--weave-px-subhead);font-weight:600;letter-spacing:.01em;white-space:nowrap}
|
|
207
|
-
.weave-brand-mark{height:20px;width:20px;border-radius:var(--weave-radius)}
|
|
208
|
-
/* A button styled as a search field: the palette owns the only text input,
|
|
209
|
-
so this opens it rather than pretending to accept a query. */
|
|
210
|
-
.weave-search{
|
|
211
|
-
display:flex;align-items:center;gap:6px;flex:0 1 260px;min-width:0;
|
|
212
|
-
height:22px;padding:0 7px;font:inherit;font-size:var(--weave-px-row);text-align:left;cursor:pointer;
|
|
213
|
-
color:var(--weave-dim);background:var(--weave-bg);
|
|
214
|
-
border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);
|
|
215
|
-
}
|
|
216
|
-
.weave-search:hover{color:var(--weave-fg);border-color:var(--weave-accent)}
|
|
217
|
-
.weave-search-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
218
|
-
.weave-search kbd{
|
|
219
|
-
font-family:var(--weave-mono);font-size:var(--weave-px-caption);color:var(--weave-faint);
|
|
220
|
-
padding:1px 5px;border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);white-space:nowrap;
|
|
221
|
-
}
|
|
222
|
-
.weave-summary{
|
|
223
|
-
margin-left:auto;display:flex;gap:9px;font-family:var(--weave-mono);
|
|
224
|
-
font-size:var(--weave-px-ui);color:var(--weave-dim);white-space:nowrap;
|
|
225
|
-
}
|
|
226
|
-
.weave-summary-part+.weave-summary-part::before{content:"·";margin-right:9px;color:var(--weave-faint)}
|
|
227
|
-
.weave-refresh{
|
|
228
|
-
font:inherit;font-size:var(--weave-px-subhead);line-height:1;color:var(--weave-dim);background:none;
|
|
229
|
-
border:0;padding:3px 5px;border-radius:var(--weave-radius);cursor:pointer;
|
|
230
|
-
display:inline-flex;align-items:center;
|
|
231
|
-
}
|
|
232
|
-
.weave-refresh:hover{color:var(--weave-fg);background:var(--weave-line)}
|
|
233
|
-
/* One full 600 ms turn per click ("the request left"), not a loop: the
|
|
234
|
-
refetch is fire-and-forget and a 304 may never fire a completion signal
|
|
235
|
-
for a spinner to wait on. Reduced-motion restores the static stroke. */
|
|
236
|
-
.weave-refresh-spinning{animation:weave-refresh-turn 600ms ease-out}
|
|
237
|
-
@keyframes weave-refresh-turn{from{transform:rotate(0)}to{transform:rotate(360deg)}}
|
|
238
|
-
/* The theme cycle (shell/theme.model.ts). Same shape as the refresh button:
|
|
239
|
-
an icon-size control in a 34 px bar, glyph-only because the filled/half/
|
|
240
|
-
hollow family already means something in this workspace. */
|
|
241
|
-
.weave-theme{
|
|
242
|
-
font:inherit;font-size:var(--weave-px-base);line-height:1;color:var(--weave-dim);background:none;
|
|
243
|
-
border:0;padding:3px 6px;border-radius:var(--weave-radius);cursor:pointer;
|
|
244
|
-
}
|
|
245
|
-
.weave-theme:hover{color:var(--weave-fg);background:var(--weave-line)}
|
|
246
|
-
|
|
247
|
-
/* the grid -------------------------------------------------------------- */
|
|
248
|
-
/* Widths arrive as custom properties from layout.model.ts. Shell/layout.model
|
|
249
|
-
selects the breakpoint; CSS consumes the resulting data-columns shape. */
|
|
250
|
-
.weave-grid{display:grid;min-height:0;overflow:hidden;background:var(--weave-line)}
|
|
251
|
-
.weave-grid[data-columns="3"]{grid-template-columns:var(--weave-col-tree,22%) 1px var(--weave-col-note,46%) 1px var(--weave-col-graph,32%)}
|
|
252
|
-
.weave-grid[data-columns="2"]{grid-template-columns:var(--weave-col-tree,32%) 1px var(--weave-col-note,68%)}
|
|
253
|
-
.weave-grid[data-columns="1"]{grid-template-columns:1fr}
|
|
254
|
-
|
|
255
|
-
/* dividers -------------------------------------------------------------- */
|
|
256
|
-
.weave-divider{
|
|
257
|
-
width:1px;cursor:col-resize;touch-action:none;background:var(--weave-line);position:relative;z-index:2;
|
|
258
|
-
}
|
|
259
|
-
.weave-divider::after{content:"";position:absolute;inset:0 -4px}
|
|
260
|
-
.weave-divider:hover{background:var(--weave-faint)}
|
|
261
|
-
.weave-divider:focus-visible{outline:2px solid var(--weave-accent);outline-offset:-1px}
|
|
262
|
-
|
|
263
|
-
.weave-col{
|
|
264
|
-
display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;
|
|
265
|
-
background:var(--weave-bg);
|
|
266
|
-
}
|
|
267
|
-
.weave-col-title{
|
|
268
|
-
margin:0;padding:5px var(--weave-gutter) 4px;font-size:var(--weave-px-caption);font-weight:600;
|
|
269
|
-
letter-spacing:.09em;text-transform:uppercase;color:var(--weave-faint);
|
|
270
|
-
border-bottom:1px solid var(--weave-line);
|
|
271
|
-
}
|
|
272
|
-
/* Title, then the graph (which takes the slack), then the context rail. The
|
|
273
|
-
1fr is what gives .weave-graph-canvas a definite height to measure, and the
|
|
274
|
-
rail's row is a fixed fraction of the column — not content-sized — so
|
|
275
|
-
moving the selection between a sparsely-connected note and a richly
|
|
276
|
-
connected one never repartitions the right-hand column: the rail scrolls
|
|
277
|
-
inside the same region instead of squeezing the graph. */
|
|
278
|
-
.weave-col-graph{display:grid;grid-template-rows:auto minmax(0,1fr) minmax(96px,40%);background:var(--weave-bg)}
|
|
119
|
+
#app{height:100%;display:grid;grid-template-rows:minmax(0,1fr) auto;background:var(--weave-bg)}
|
|
279
120
|
|
|
280
121
|
/* tree column ----------------------------------------------------------- */
|
|
281
122
|
/* --weave-depth is written per row by \`depthVar\`, through CSSOM
|
|
@@ -487,8 +328,8 @@ body{font-size:var(--weave-px-base)}
|
|
|
487
328
|
text-decoration-thickness:1px;text-underline-offset:2px;
|
|
488
329
|
}
|
|
489
330
|
.weave-note-body a:hover{text-decoration-color:var(--weave-accent)}
|
|
490
|
-
/* A ghost is a name with no note behind it:
|
|
491
|
-
|
|
331
|
+
/* A ghost is a name with no note behind it: a dashed, dimmed affordance to
|
|
332
|
+
create one. */
|
|
492
333
|
.weave-wiki{cursor:pointer;color:var(--weave-accent);text-decoration:none}
|
|
493
334
|
.weave-wiki:hover{text-decoration:underline}
|
|
494
335
|
.weave-wiki-ghost{
|
|
@@ -550,15 +391,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
550
391
|
faster than a dark one under a black veil. */
|
|
551
392
|
.weave-graph-canvas::after{
|
|
552
393
|
content:"";position:absolute;inset:0;pointer-events:none;
|
|
553
|
-
background:
|
|
554
|
-
}
|
|
555
|
-
:root[data-weave-theme="light"] .weave-graph-canvas::after{
|
|
556
|
-
background:radial-gradient(ellipse at center,transparent 55%,rgba(76,79,105,.10) 100%);
|
|
557
|
-
}
|
|
558
|
-
@media (prefers-color-scheme: light){
|
|
559
|
-
:root:not([data-weave-theme="dark"]) .weave-graph-canvas::after{
|
|
560
|
-
background:radial-gradient(ellipse at center,transparent 55%,rgba(76,79,105,.10) 100%);
|
|
561
|
-
}
|
|
394
|
+
background:var(--weave-vignette);
|
|
562
395
|
}
|
|
563
396
|
.weave-graph-empty{
|
|
564
397
|
margin:0;padding:14px var(--weave-gutter);color:var(--weave-dim);
|
|
@@ -584,32 +417,6 @@ body{font-size:var(--weave-px-base)}
|
|
|
584
417
|
border-top:1px solid var(--weave-line);
|
|
585
418
|
}
|
|
586
419
|
|
|
587
|
-
/* the hidden force tuner (?sliders=1, docs/weave-workspace.md 15.7) --------- */
|
|
588
|
-
/* Absolutely positioned over the canvas rather than given a grid row: the
|
|
589
|
-
panel is a debug overlay and must not change the layout the graph is being
|
|
590
|
-
judged in — moving the canvas while tuning it would falsify the very thing
|
|
591
|
-
being looked at. */
|
|
592
|
-
.weave-tuner{
|
|
593
|
-
position:absolute;top:8px;right:8px;z-index:3;width:232px;max-height:calc(100% - 16px);
|
|
594
|
-
overflow:auto;display:flex;flex-direction:column;gap:6px;padding:9px 10px;
|
|
595
|
-
font-size:var(--weave-px-caption);color:var(--weave-fg);
|
|
596
|
-
background:var(--weave-panel);border:1px solid var(--weave-line-strong);
|
|
597
|
-
border-radius:var(--weave-radius);
|
|
598
|
-
}
|
|
599
|
-
.weave-tuner-title{margin:0;color:var(--weave-faint);letter-spacing:.04em;text-transform:uppercase}
|
|
600
|
-
.weave-tuner-row{display:flex;flex-direction:column;gap:2px;cursor:pointer}
|
|
601
|
-
.weave-tuner-label{display:flex;justify-content:space-between;gap:8px;color:var(--weave-dim)}
|
|
602
|
-
.weave-tuner-label b{color:var(--weave-accent);font-weight:600;font-variant-numeric:tabular-nums}
|
|
603
|
-
.weave-tuner-row input{width:100%;margin:0;accent-color:var(--weave-accent)}
|
|
604
|
-
.weave-tuner-toggle{display:flex;align-items:center;gap:6px;cursor:pointer;color:var(--weave-dim)}
|
|
605
|
-
.weave-tuner-toggle input{margin:0;accent-color:var(--weave-accent)}
|
|
606
|
-
.weave-tuner-actions{display:flex;gap:6px;margin-top:2px;flex-wrap:wrap}
|
|
607
|
-
.weave-tuner-snippet{
|
|
608
|
-
margin:0;padding:6px;overflow:auto;white-space:pre;color:var(--weave-faint);
|
|
609
|
-
background:var(--weave-bg);border:1px solid var(--weave-line);border-radius:var(--weave-radius);
|
|
610
|
-
font-size:var(--weave-px-prov);line-height:1.45;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
420
|
/* context rail ---------------------------------------------------------- */
|
|
614
421
|
/* The \`.weave-empty\` block that used to sit above went with \`EmptyState.tsx\`
|
|
615
422
|
in P3: every column now has its own empty state (\`treeEmptyMessage\`,
|
|
@@ -633,9 +440,8 @@ body{font-size:var(--weave-px-base)}
|
|
|
633
440
|
text-align:left;background:none;border:0;cursor:pointer;
|
|
634
441
|
}
|
|
635
442
|
.weave-ctx-heading:hover{color:var(--weave-fg)}
|
|
636
|
-
/* The count is a mono voice
|
|
637
|
-
|
|
638
|
-
"BACKLINKS 4" in the text face would be the one thing off-key. */
|
|
443
|
+
/* The count is a mono voice like the other status numbers, so a rail that
|
|
444
|
+
says "BACKLINKS 4" in the text face would be the one thing off-key. */
|
|
639
445
|
.weave-ctx-count{
|
|
640
446
|
margin-left:auto;font-family:var(--weave-mono);font-size:var(--weave-px-caption);
|
|
641
447
|
letter-spacing:0;color:var(--weave-faint);font-weight:400;
|
|
@@ -662,11 +468,8 @@ body{font-size:var(--weave-px-base)}
|
|
|
662
468
|
.weave-ctx-tag{margin:0 0 3px}
|
|
663
469
|
.weave-ctx-tag .weave-ctx-rows{padding-left:12px}
|
|
664
470
|
|
|
665
|
-
/*
|
|
666
|
-
/*
|
|
667
|
-
status items after the first opens with the same mid-dot, in the same
|
|
668
|
-
--weave-faint. cwd · selection · stamp reads as one grammar,
|
|
669
|
-
the same way the header's three-part summary does. */
|
|
471
|
+
/* workspace footer ------------------------------------------------------ */
|
|
472
|
+
/* The status items share one mid-dot separator in --weave-faint. */
|
|
670
473
|
.weave-status{
|
|
671
474
|
display:flex;align-items:center;gap:8px;height:22px;padding:0 var(--weave-gutter);
|
|
672
475
|
font-family:var(--weave-mono);font-size:var(--weave-px-ui);color:var(--weave-dim);
|
|
@@ -676,7 +479,6 @@ body{font-size:var(--weave-px-base)}
|
|
|
676
479
|
.weave-status-cwd,.weave-status-sel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
677
480
|
.weave-status-cwd{max-width:38%;color:var(--weave-faint)}
|
|
678
481
|
.weave-status-sel{color:var(--weave-fg)}
|
|
679
|
-
.weave-status-stamp{margin-left:auto;color:var(--weave-faint)}
|
|
680
482
|
|
|
681
483
|
/* overlays: the ⌘K palette and the ? help sheet (P4) --------------------- */
|
|
682
484
|
/* The scrim is a click target that closes, and the reason both overlays sit
|
|
@@ -685,15 +487,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
685
487
|
the wrong breakpoint. */
|
|
686
488
|
.weave-scrim{
|
|
687
489
|
position:fixed;inset:0;z-index:10;display:flex;justify-content:center;
|
|
688
|
-
align-items:flex-start;padding:9vh 16px 16px;background:
|
|
689
|
-
}
|
|
690
|
-
/* The scrim above is tuned for the dark ground, where a neutral black veil
|
|
691
|
-
reads as depth. On the linen ground the same veil reads as a power cut, so
|
|
692
|
-
the light scheme gets its own — a plum-tinted veil at reduced strength,
|
|
693
|
-
drawn from the foreground ramp rather than from grey. */
|
|
694
|
-
:root[data-weave-theme="light"] .weave-scrim{background:rgba(76,79,105,.30)}
|
|
695
|
-
@media (prefers-color-scheme: light){
|
|
696
|
-
:root:not([data-weave-theme="dark"]) .weave-scrim{background:rgba(76,79,105,.30)}
|
|
490
|
+
align-items:flex-start;padding:9vh 16px 16px;background:var(--weave-scrim);
|
|
697
491
|
}
|
|
698
492
|
.weave-palette,.weave-help{
|
|
699
493
|
display:flex;flex-direction:column;width:100%;max-width:560px;max-height:72vh;
|
|
@@ -760,7 +554,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
760
554
|
would need delay-unmount plumbing far past polish. Compositor-safe
|
|
761
555
|
properties only — colour, border, opacity, transform; height and padding
|
|
762
556
|
snap. */
|
|
763
|
-
.weave-row,.weave-ctx-link,.weave-chip,.weave-
|
|
557
|
+
.weave-row,.weave-ctx-link,.weave-chip,.weave-ribbon button,
|
|
764
558
|
.weave-hit,.weave-note-open{
|
|
765
559
|
transition:background-color 120ms ease,border-color 120ms ease,color 120ms ease;
|
|
766
560
|
}
|
|
@@ -826,7 +620,7 @@ export function findNonce(host: ThemeHost): string | null {
|
|
|
826
620
|
* report in the console is a far better diagnostic than a stylesheet that was
|
|
827
621
|
* never created.
|
|
828
622
|
*/
|
|
829
|
-
export function installTheme(host: ThemeHost, css: string = THEME_CSS): boolean {
|
|
623
|
+
export function installTheme(host: ThemeHost, css: string = THEME_CSS + WORKSPACE_CSS): boolean {
|
|
830
624
|
const element = host.createElement("style");
|
|
831
625
|
const nonce = findNonce(host);
|
|
832
626
|
if (nonce !== null) element.nonce = nonce;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/** Tabbed workspace furniture; the graph keeps its existing palette and renderer. */
|
|
2
|
+
export const WORKSPACE_CSS = `
|
|
3
|
+
.weave-workbench{position:relative;display:flex;min-height:0;overflow:hidden;background:var(--weave-page)}
|
|
4
|
+
.weave-workbench button{font:inherit;color:inherit;cursor:pointer}
|
|
5
|
+
.weave-workbench button:focus-visible,.weave-workbench summary:focus-visible{outline:2px solid var(--weave-accent);outline-offset:-2px}
|
|
6
|
+
.weave-workbench button:disabled{opacity:.35;cursor:default}
|
|
7
|
+
.weave-ribbon{width:44px;flex:none;display:flex;align-items:center;flex-direction:column;gap:8px;padding:12px 0;background:var(--weave-panel);border-right:1px solid var(--weave-line)}
|
|
8
|
+
.weave-ribbon button{width:32px;height:32px;border:0;border-radius:var(--weave-radius);background:transparent;font-size:var(--weave-px-display);color:var(--weave-dim)}
|
|
9
|
+
.weave-ribbon button:hover,.weave-ribbon button[aria-pressed=true]{color:var(--weave-accent);background:var(--weave-new)}
|
|
10
|
+
.weave-ribbon-space{flex:1}
|
|
11
|
+
.weave-sidebar{flex:none;min-width:0;display:flex;flex-direction:column;background:var(--weave-panel);overflow:hidden}
|
|
12
|
+
.weave-sidebar-dock{display:flex;flex:none;min-width:0;width:calc(var(--weave-sidebar-width) + 4px);overflow:hidden;opacity:1;visibility:visible;transition:width 200ms ease,opacity 160ms ease,visibility 0s}
|
|
13
|
+
.weave-sidebar-dock[data-open=false]{width:0;opacity:0;visibility:hidden;transition:width 200ms ease,opacity 160ms ease,visibility 0s 200ms}
|
|
14
|
+
.weave-sidebar-dock>.weave-sidebar{width:var(--weave-sidebar-width);transition:transform 200ms ease}
|
|
15
|
+
.weave-sidebar-dock[data-open=false]>.weave-sidebar{transform:translateX(-16px)}
|
|
16
|
+
.weave-context-dock[data-open=false]>.weave-sidebar{transform:translateX(16px)}
|
|
17
|
+
.weave-sidebar-heading{display:flex;align-items:center;gap:8px;height:46px;flex:none;padding:0 12px;color:var(--weave-dim);font-size:var(--weave-px-row)}
|
|
18
|
+
.weave-sidebar-heading button{border:0;background:none;padding:7px 6px;border-radius:var(--weave-radius);color:var(--weave-dim)}
|
|
19
|
+
.weave-sidebar-heading button[aria-pressed=true]{color:var(--weave-fg);background:var(--weave-raise)}
|
|
20
|
+
.weave-sidebar-heading button:last-child{margin-left:auto}
|
|
21
|
+
.weave-sidebar .weave-tree-controls{padding:4px 12px 10px;gap:5px;flex-wrap:wrap;border:0}
|
|
22
|
+
.weave-sidebar .weave-filter{height:29px;flex-basis:100%;background:var(--weave-bg);border-radius:var(--weave-radius)}
|
|
23
|
+
.weave-sidebar .weave-row{min-height:32px;border-radius:var(--weave-radius);font-size:var(--weave-px-base)}
|
|
24
|
+
.weave-sidebar [role=tree]{padding:0 8px}
|
|
25
|
+
.weave-sidebar .weave-meta{font-size:var(--weave-px-caption);opacity:.65}
|
|
26
|
+
.weave-sidebar .weave-tree-count{border:0;padding:8px 14px}
|
|
27
|
+
.weave-vault-label{margin-top:auto;padding:14px 16px;border-top:1px solid var(--weave-line);display:flex;flex-direction:column;gap:4px;overflow:hidden}
|
|
28
|
+
.weave-vault-label span{font-size:var(--weave-px-caption);color:var(--weave-faint);text-transform:uppercase;letter-spacing:.08em}
|
|
29
|
+
.weave-vault-label strong{font-size:var(--weave-px-row);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
30
|
+
.weave-recents{display:flex;flex-direction:column;gap:3px;padding:6px 10px;overflow:auto}
|
|
31
|
+
.weave-recents button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:0;padding:9px;border-radius:var(--weave-radius);overflow:hidden}
|
|
32
|
+
.weave-recents button:hover{background:var(--weave-new)}
|
|
33
|
+
.weave-recents button[aria-current=page]{background:var(--weave-raise);color:var(--weave-fg)}
|
|
34
|
+
.weave-recents .weave-recent-label{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
35
|
+
.weave-workspace-divider{flex:none;width:4px;background:var(--weave-panel);cursor:col-resize;touch-action:none;z-index:3}
|
|
36
|
+
.weave-workspace-divider:hover,.weave-workspace-divider:focus-visible{background:var(--weave-accent)}
|
|
37
|
+
.weave-workspace-divider[aria-orientation=horizontal]{width:auto;height:4px;cursor:row-resize}
|
|
38
|
+
.weave-panes{display:grid;flex:1;min-width:0;min-height:0;overflow:hidden}
|
|
39
|
+
.weave-pane{min-width:0;min-height:0;display:grid;grid-template-rows:42px 36px minmax(0,1fr);overflow:hidden;background:var(--weave-page)}
|
|
40
|
+
.weave-pane[hidden]{display:none}
|
|
41
|
+
.weave-pane-drop{position:relative}
|
|
42
|
+
.weave-pane-drop::after{content:attr(data-drop-label);position:absolute;inset:4px;z-index:20;display:grid;place-items:center;pointer-events:none;border:2px dashed var(--weave-accent);border-radius:var(--weave-radius);color:var(--weave-accent);background:var(--weave-new)}
|
|
43
|
+
.weave-tabs{display:flex;align-items:stretch;min-width:0;overflow-x:auto;background:var(--weave-panel);gap:3px;padding:5px 6px 0;border-bottom:1px solid var(--weave-line);scrollbar-width:thin}
|
|
44
|
+
.weave-tab{position:relative;display:flex;align-items:center;min-width:90px;max-width:210px;border-radius:var(--weave-radius) var(--weave-radius) 0 0;color:var(--weave-dim);flex-shrink:0;border-bottom:2px solid transparent}
|
|
45
|
+
.weave-tab-drop-before::before,.weave-tab-drop-after::after{content:"";position:absolute;top:2px;bottom:2px;width:3px;background:var(--weave-accent);pointer-events:none}
|
|
46
|
+
.weave-tab-drop-before::before{left:-3px}.weave-tab-drop-after::after{right:-3px}
|
|
47
|
+
.weave-tab-active{background:var(--weave-page);color:var(--weave-fg)}
|
|
48
|
+
.weave-pane-active .weave-tab-active{border-bottom-color:var(--weave-accent)}
|
|
49
|
+
.weave-tab button{border:0;background:none}
|
|
50
|
+
.weave-tab [role=tab]{display:flex;align-items:center;gap:8px;text-align:left;padding:8px 9px;min-width:0;height:100%;font-size:var(--weave-px-row)}
|
|
51
|
+
.weave-tab [role=tab]>span:nth-child(2){white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
52
|
+
.weave-tab [role=tab]>span:first-child{color:var(--weave-faint)}
|
|
53
|
+
.weave-tab .weave-tab-close{margin-right:4px;padding:2px 5px;font-size:var(--weave-px-subhead);color:var(--weave-faint)}
|
|
54
|
+
.weave-tab-close:hover{color:var(--weave-fg);background:var(--weave-raise)}
|
|
55
|
+
.weave-dirty{font-size:var(--weave-px-prov);color:var(--weave-accent)}
|
|
56
|
+
.weave-new-tab{border:0;background:none;padding:4px 10px;font-size:var(--weave-px-display)!important;color:var(--weave-dim)!important}
|
|
57
|
+
.weave-pane-toolbar{display:flex;align-items:center;gap:5px;padding:0 10px;border-bottom:1px solid var(--weave-line);color:var(--weave-dim);font-size:var(--weave-px-row)}
|
|
58
|
+
.weave-pane-toolbar>button{width:26px;height:26px;border:0;background:none;border-radius:var(--weave-radius)}
|
|
59
|
+
.weave-pane-toolbar>button:hover{background:var(--weave-new)}
|
|
60
|
+
.weave-breadcrumb{flex:1;text-align:center;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 8px;font-size:var(--weave-px-ui)}
|
|
61
|
+
.weave-pane-menu{position:relative}
|
|
62
|
+
.weave-pane-menu>summary{list-style:none;cursor:pointer;padding:5px 10px;font-size:var(--weave-px-subhead)}
|
|
63
|
+
.weave-pane-menu>summary::-webkit-details-marker{display:none}
|
|
64
|
+
.weave-pane-menu>div{position:absolute;right:0;top:100%;z-index:12;width:185px;padding:5px;display:flex;flex-direction:column;background:var(--weave-panel);border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius)}
|
|
65
|
+
.weave-pane-menu button{text-align:left;border:0;background:none;padding:9px 10px;font-size:var(--weave-px-row)}
|
|
66
|
+
.weave-pane-menu button:hover{background:var(--weave-new)}
|
|
67
|
+
.weave-pane-content{min-width:0;min-height:0;display:flex;overflow:hidden;position:relative}
|
|
68
|
+
.weave-document{display:flex;min-width:0;min-height:0;flex:1}
|
|
69
|
+
.weave-document .weave-note{width:100%;border-left:0}
|
|
70
|
+
.weave-document .weave-note-head{position:static;padding:28px max(24px,calc((100% - var(--weave-reading-width,760px))/2)) 18px;border:0}
|
|
71
|
+
.weave-document .weave-note-title{font-size:var(--weave-px-display);letter-spacing:-.03em;margin-bottom:12px}
|
|
72
|
+
.weave-document .weave-note-body{padding:10px max(24px,calc((100% - var(--weave-reading-width,760px))/2)) 64px;font-size:var(--weave-note-size,var(--weave-px-subhead));line-height:1.8}
|
|
73
|
+
.weave-document .weave-note-body h1{font-size:var(--weave-px-display);line-height:1.4;margin-bottom:18px}
|
|
74
|
+
.weave-document .weave-note-body h2{font-size:var(--weave-px-title);margin-top:28px}
|
|
75
|
+
.weave-document .weave-note-editor{padding:14px max(24px,calc((100% - var(--weave-reading-width,760px))/2));min-height:220px;flex:1;font-size:var(--weave-note-size,var(--weave-px-subhead))}
|
|
76
|
+
.weave-document .weave-note-tags{margin-top:12px}
|
|
77
|
+
.weave-document .weave-note-edit,.weave-document .weave-note-save{padding:5px 10px;border-radius:var(--weave-radius)}
|
|
78
|
+
.weave-welcome{align-self:center;margin:auto;padding:35px;max-width:560px;color:var(--weave-dim);line-height:1.7}
|
|
79
|
+
.weave-welcome-mark{font-size:var(--weave-px-display);color:var(--weave-accent)}
|
|
80
|
+
.weave-welcome h1{font-size:var(--weave-px-display);line-height:1.4;letter-spacing:-.025em;color:var(--weave-fg);font-weight:550}
|
|
81
|
+
.weave-welcome p{font-size:var(--weave-px-base);margin:14px 0 24px}
|
|
82
|
+
.weave-welcome>div{display:flex;gap:12px;flex-wrap:wrap}
|
|
83
|
+
.weave-welcome button{border:1px solid var(--weave-line-strong);background:var(--weave-panel);padding:9px 13px;border-radius:var(--weave-radius);font-size:var(--weave-px-row)}
|
|
84
|
+
.weave-welcome button:hover{border-color:var(--weave-accent)}
|
|
85
|
+
.weave-welcome kbd{color:var(--weave-faint);padding-left:16px}
|
|
86
|
+
.weave-sidebar-context .weave-rail{flex:1;border:0;overflow:auto;padding:6px 12px}
|
|
87
|
+
.weave-sidebar-context .weave-ctx-link{padding-top:7px;padding-bottom:7px}
|
|
88
|
+
.weave-graph-host{position:absolute;z-index:2;display:flex;background:var(--weave-bg)}
|
|
89
|
+
.weave-graph-host>.weave-graph{width:100%;height:100%;flex:1}
|
|
90
|
+
.weave-graph-preview{pointer-events:none;position:absolute;z-index:2;right:8px;bottom:64px;width:min(280px,calc(100% - 16px));box-sizing:border-box;display:flex;flex-direction:column;gap:8px;padding:10px 34px 10px 10px;background:var(--weave-panel);border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);box-shadow:0 6px 22px #0003}
|
|
91
|
+
.weave-graph-preview-info{display:flex;align-items:center;gap:8px;min-width:0}
|
|
92
|
+
.weave-graph-preview-copy{display:flex;flex-direction:column;min-width:0;gap:2px}
|
|
93
|
+
.weave-graph-preview-kind{font-size:var(--weave-px-caption);color:var(--weave-faint);text-transform:capitalize}
|
|
94
|
+
.weave-graph-preview-title{font-size:var(--weave-px-row);font-weight:550;line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow-wrap:anywhere}
|
|
95
|
+
.weave-graph-preview-close{pointer-events:auto;position:absolute;right:5px;top:5px;width:24px;height:24px;border:0;border-radius:var(--weave-radius);background:transparent;font-size:18px;color:var(--weave-dim)}
|
|
96
|
+
.weave-graph-preview-close:hover{background:var(--weave-new);color:var(--weave-fg)}
|
|
97
|
+
.weave-graph-preview>.weave-chip{pointer-events:auto;align-self:flex-start;max-width:100%;white-space:normal;text-align:left}
|
|
98
|
+
.weave-footer{display:flex;align-items:center;min-width:0;background:var(--weave-panel);border-top:1px solid var(--weave-line);font-size:var(--weave-px-ui);color:var(--weave-faint)}
|
|
99
|
+
.weave-footer>.weave-status{flex:1;min-width:0;border:0}
|
|
100
|
+
.weave-footer>span{padding:4px 10px;white-space:nowrap}
|
|
101
|
+
.weave-footer>button{font:inherit;color:var(--weave-fg);background:none;border:0;padding:7px 12px;cursor:pointer}
|
|
102
|
+
@media(max-width:1049px){
|
|
103
|
+
.weave-context-dock{position:absolute;right:0;top:0;bottom:0;z-index:10;width:var(--weave-sidebar-width)}
|
|
104
|
+
.weave-sidebar-context{border-left:1px solid var(--weave-line-strong)}
|
|
105
|
+
.weave-context-dock>.weave-workspace-divider{display:none}
|
|
106
|
+
}
|
|
107
|
+
@media(max-width:849px){
|
|
108
|
+
.weave-notes-dock{position:absolute;left:44px;top:0;bottom:0;z-index:10;width:var(--weave-sidebar-width);box-shadow:8px 0 24px #0002}
|
|
109
|
+
.weave-sidebar-notes{border-right:1px solid var(--weave-line-strong)}
|
|
110
|
+
.weave-notes-dock>.weave-workspace-divider{display:none}
|
|
111
|
+
.weave-workbench>.weave-workspace-divider{display:none}
|
|
112
|
+
.weave-panes{grid-template-columns:minmax(0,1fr)!important;grid-template-rows:minmax(0,1fr)!important}
|
|
113
|
+
.weave-document .weave-note-head{padding:20px}
|
|
114
|
+
.weave-document .weave-note-body{padding:10px 20px 40px}
|
|
115
|
+
}
|
|
116
|
+
@media(prefers-reduced-motion:reduce){
|
|
117
|
+
.weave-sidebar-dock,.weave-sidebar-dock[data-open=false],.weave-sidebar-dock>.weave-sidebar{transition:none}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.weave-settings-scrim{align-items:center;padding:24px 16px}
|
|
121
|
+
.weave-settings button{font:inherit;color:inherit;cursor:pointer;border:0;background:transparent}
|
|
122
|
+
.weave-settings a{color:var(--weave-accent)}
|
|
123
|
+
.weave-settings{display:grid;grid-template-columns:180px minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);width:min(900px,calc(100vw - 32px));height:min(680px,calc(100dvh - 48px));background:var(--weave-panel);border:1px solid var(--weave-line-strong);border-radius:12px;box-shadow:0 24px 80px var(--weave-scrim);overflow:hidden}
|
|
124
|
+
.weave-settings header{grid-column:1/-1;display:flex;justify-content:space-between;align-items:center;padding:16px 24px;border-bottom:1px solid var(--weave-line)}
|
|
125
|
+
.weave-settings h2,.weave-settings h3{margin:0}.weave-settings h3{font-size:20px;margin-bottom:24px}
|
|
126
|
+
.weave-settings header button{font-size:24px}.weave-settings nav{padding:16px 12px;background:var(--weave-bg);overflow:auto;border-right:1px solid var(--weave-line)}
|
|
127
|
+
.weave-settings nav button{display:block;width:100%;text-align:left;padding:10px 12px;border-radius:6px;color:var(--weave-dim)}
|
|
128
|
+
.weave-settings nav button[aria-current]{color:var(--weave-accent);background:var(--weave-new)}
|
|
129
|
+
.weave-settings section{padding:28px;overflow:auto;min-width:0}.weave-settings p{line-height:1.6;color:var(--weave-dim)}
|
|
130
|
+
.weave-setting-row{display:flex;justify-content:space-between;align-items:center;gap:24px;padding:16px 0;border-bottom:1px solid var(--weave-line)}
|
|
131
|
+
.weave-setting-row>span:first-child{min-width:0;flex:1}.weave-setting-row strong{display:block;font-weight:500}.weave-setting-row small{display:block;color:var(--weave-dim);margin-top:6px;line-height:1.5}
|
|
132
|
+
.weave-settings select{background:var(--weave-raise);border:1px solid var(--weave-line-strong);border-radius:6px;padding:7px;color:var(--weave-fg);max-width:230px;font:inherit}
|
|
133
|
+
.weave-settings input{accent-color:var(--weave-accent)}.weave-settings input[type=checkbox]{width:18px;height:18px;flex-shrink:0}
|
|
134
|
+
.weave-setting-range{display:flex;align-items:center;gap:12px;width:190px}.weave-setting-range input{width:130px;min-width:0}.weave-setting-range output{min-width:42px;text-align:right;color:var(--weave-accent);font-variant-numeric:tabular-nums}
|
|
135
|
+
.weave-settings button:focus-visible,.weave-settings a:focus-visible,.weave-settings summary:focus-visible{outline:2px solid var(--weave-accent);outline-offset:2px}
|
|
136
|
+
.weave-settings-actions{display:flex;gap:16px;align-items:center;flex-wrap:wrap;margin:24px 0}.weave-settings-actions button,.weave-settings-download,.weave-settings-forces>button{display:inline-block;padding:9px 14px;border:1px solid var(--weave-line-strong);border-radius:6px;color:var(--weave-accent);background:var(--weave-raise);text-decoration:none}
|
|
137
|
+
.weave-settings-forces>button{margin-top:20px}.weave-settings-forces>button:disabled{opacity:.5}.weave-settings-locations dd{margin:6px 0 18px;overflow-wrap:anywhere;color:var(--weave-dim);font-family:var(--weave-font-mono)}
|
|
138
|
+
.weave-settings details summary{cursor:pointer;padding:12px 0}.weave-settings .weave-key-row{gap:16px;align-items:baseline}.weave-settings .weave-key-row kbd{min-width:150px;color:var(--weave-accent)}
|
|
139
|
+
@media(max-width:650px){.weave-settings{grid-template-columns:1fr;grid-template-rows:auto auto minmax(0,1fr)}.weave-settings nav{border-right:0;border-bottom:1px solid var(--weave-line);padding:8px 16px}.weave-settings nav select{width:100%;max-width:none}.weave-settings section{padding:20px}.weave-setting-row{align-items:flex-start;gap:12px}.weave-settings select{max-width:170px}.weave-setting-range{width:140px}.weave-setting-range input{width:90px}}
|
|
140
|
+
`;
|