visualproof 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +99 -2
- package/dist/assets/fonts/JuliaMono-Regular.ttf +0 -0
- package/dist/assets/fonts/JuliaMono-RegularItalic.ttf +0 -0
- package/dist/assets/fonts/JuliaMono-SemiBold.ttf +0 -0
- package/dist/assets/fonts/LICENSE-JuliaMono.txt +93 -0
- package/dist/assets/latex/visualproof.sty +308 -0
- package/dist/extractor/Extract.lean +1180 -0
- package/dist/extractor/Usage.lean +900 -0
- package/dist/mcp/visualproof-mcp.mjs +476 -0
- package/dist/server/access.js +95 -0
- package/dist/server/agent.js +3235 -0
- package/dist/server/agentdocs.js +35 -0
- package/dist/server/agentlibrary.js +202 -0
- package/dist/server/agentnotes.js +701 -0
- package/dist/server/agentviews.js +703 -0
- package/dist/server/askfollow.js +286 -0
- package/dist/server/boardspots.js +159 -0
- package/dist/server/dirs.js +175 -0
- package/dist/server/doctor.js +186 -0
- package/dist/server/events.js +198 -0
- package/dist/server/export.js +420 -0
- package/dist/server/extract.js +204 -0
- package/dist/server/fetchurl.js +321 -0
- package/dist/server/figures.js +158 -0
- package/dist/server/history.js +741 -0
- package/dist/server/historyapi.js +304 -0
- package/dist/server/hover.js +595 -0
- package/dist/server/identity.js +114 -0
- package/dist/server/invites.js +241 -0
- package/dist/server/layoutthread.js +51 -0
- package/dist/server/library.js +600 -0
- package/dist/server/libraryroute.js +211 -0
- package/dist/server/live.js +1101 -0
- package/dist/server/lostfound.js +199 -0
- package/dist/server/main.js +1394 -0
- package/dist/server/mcptools.js +497 -0
- package/dist/server/pastdoc.js +73 -0
- package/dist/server/pipeline.js +156 -0
- package/dist/server/poppler.js +251 -0
- package/dist/server/presence.js +252 -0
- package/dist/server/project.js +222 -0
- package/dist/server/prompt.js +53 -0
- package/dist/server/readonly.js +152 -0
- package/dist/server/readonlygate.js +123 -0
- package/dist/server/renames.js +268 -0
- package/dist/server/review.js +334 -0
- package/dist/server/reviewapi.js +188 -0
- package/dist/server/snapshot.js +49 -0
- package/dist/server/sourcestore.js +473 -0
- package/dist/server/status.js +360 -0
- package/dist/server/talk.js +476 -0
- package/dist/server/tokens.js +221 -0
- package/dist/server/usage.js +501 -0
- package/dist/server/versions.js +82 -0
- package/dist/server/view.js +157 -0
- package/dist/server/views.js +1167 -0
- package/dist/shared/askfollow.js +46 -0
- package/dist/shared/board.js +332 -0
- package/dist/shared/build.js +2 -0
- package/dist/shared/collab.js +148 -0
- package/dist/shared/comment.js +285 -0
- package/dist/shared/context.js +157 -0
- package/dist/shared/doc/authors.js +98 -0
- package/dist/shared/doc/build.js +358 -0
- package/dist/shared/doc/latex.js +455 -0
- package/dist/shared/doc/markdown.js +159 -0
- package/dist/shared/doc/model.js +37 -0
- package/dist/shared/doc/order.js +107 -0
- package/dist/shared/doc/proof.js +272 -0
- package/dist/shared/doc/sections.js +93 -0
- package/dist/shared/doc/settings.js +75 -0
- package/dist/shared/edgecodec.js +102 -0
- package/dist/shared/editor.js +64 -0
- package/dist/shared/excerpt.js +87 -0
- package/dist/shared/graph.js +16 -0
- package/dist/shared/items.js +92 -0
- package/dist/shared/keys.js +203 -0
- package/dist/shared/layout.js +926 -0
- package/dist/shared/lexer.js +130 -0
- package/dist/shared/library.js +711 -0
- package/dist/shared/lostfound.js +150 -0
- package/dist/shared/moves.js +243 -0
- package/dist/shared/notecard.js +295 -0
- package/dist/shared/noteplace.js +505 -0
- package/dist/shared/palette.js +46 -0
- package/dist/shared/pastgraph.js +95 -0
- package/dist/shared/places.js +80 -0
- package/dist/shared/projectnotes.js +244 -0
- package/dist/shared/query.js +810 -0
- package/dist/shared/review.js +642 -0
- package/dist/shared/reviewqueue.js +333 -0
- package/dist/shared/ring.js +366 -0
- package/dist/shared/scope.js +255 -0
- package/dist/shared/scopeedit.js +81 -0
- package/dist/shared/search.js +191 -0
- package/dist/shared/separate.js +178 -0
- package/dist/shared/sharesnap.js +280 -0
- package/dist/shared/sticky.js +501 -0
- package/dist/shared/timeline.js +73 -0
- package/dist/shared/titles.js +298 -0
- package/dist/shared/viewgraph.js +139 -0
- package/dist/shared/views.js +859 -0
- package/dist/web/bundle/app.js +48733 -0
- package/dist/web/bundle/edges.js +409 -0
- package/dist/web/bundle/layout.js +1010 -0
- package/dist/web/bundle/pdfworker.js +48322 -0
- package/dist/web/index.html +239 -0
- package/dist/web/src/motion.js +430 -0
- package/dist/web/src/past.js +224 -0
- package/dist/web/src/scene.js +787 -0
- package/dist/web/style.css +2312 -0
- package/docs/agent-api/README.md +91 -0
- package/docs/agent-api/advice.md +108 -0
- package/docs/agent-api/export.md +120 -0
- package/docs/agent-api/following.md +140 -0
- package/docs/agent-api/history.md +142 -0
- package/docs/agent-api/library.md +65 -0
- package/docs/agent-api/mcp.md +104 -0
- package/docs/agent-api/notes.md +93 -0
- package/docs/agent-api/reading.md +166 -0
- package/docs/agent-api/requests.md +94 -0
- package/docs/agent-api/talking.md +100 -0
- package/docs/agent-api/tcb.md +135 -0
- package/docs/agent-api/views.md +124 -0
- package/docs/agent-api/words.md +56 -0
- package/package.json +39 -4
- package/test/toolchains.json +5 -0
|
@@ -0,0 +1,2312 @@
|
|
|
1
|
+
/* VisualProof — quiet surfaces, one gradient for what matters. */
|
|
2
|
+
|
|
3
|
+
/* `hidden` hides, whatever display a class gives the element (the tooltip's `display: flex` kept
|
|
4
|
+
it on screen after it was hidden) */
|
|
5
|
+
[hidden] { display: none !important; }
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
--font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", Roboto, sans-serif;
|
|
9
|
+
--mono: "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
|
|
10
|
+
|
|
11
|
+
--canvas: #f5f5f7;
|
|
12
|
+
--surface: rgba(255, 255, 255, 0.78);
|
|
13
|
+
--surface-solid: #ffffff;
|
|
14
|
+
--line: rgba(0, 0, 0, 0.08);
|
|
15
|
+
--text: #1d1d1f;
|
|
16
|
+
--text-2: #6e6e73;
|
|
17
|
+
--text-3: #a1a1a6;
|
|
18
|
+
--disc: rgba(0, 0, 0, 0.022);
|
|
19
|
+
--disc-line: rgba(0, 0, 0, 0.07);
|
|
20
|
+
--label: rgba(29, 29, 31, 0.55);
|
|
21
|
+
--shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 8px 28px rgba(0, 0, 0, 0.09);
|
|
22
|
+
--shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.06), 0 22px 60px rgba(0, 0, 0, 0.14);
|
|
23
|
+
--code-bg: rgba(0, 0, 0, 0.035);
|
|
24
|
+
|
|
25
|
+
--grad: linear-gradient(100deg, #5e5ce6 0%, #bf5af2 52%, #ff375f 100%);
|
|
26
|
+
--grad-tcb: linear-gradient(100deg, #5e5ce6, #bf5af2);
|
|
27
|
+
--grad-dep: linear-gradient(100deg, #0a84ff, #64d2ff);
|
|
28
|
+
--grad-app: linear-gradient(100deg, #ff9f0a, #ff375f);
|
|
29
|
+
--accent: #7d5cf0;
|
|
30
|
+
/* the mark of someone invited by a personal link (CollabSpec decision 9): the accent, apart from
|
|
31
|
+
every colour of the review's status */
|
|
32
|
+
--verified: #6a4be0;
|
|
33
|
+
/* an edge runs from the declaration that uses (from) to the one it uses (to) */
|
|
34
|
+
--edge-from: rgba(240, 110, 20, 0.85);
|
|
35
|
+
--edge-to: rgba(59, 91, 219, 0.85);
|
|
36
|
+
|
|
37
|
+
--k-def: #0a84ff;
|
|
38
|
+
--k-abbrev: #40c8e0;
|
|
39
|
+
--k-structure: #30b158;
|
|
40
|
+
--k-class: #2fa37a;
|
|
41
|
+
--k-inductive: #63c75d;
|
|
42
|
+
--k-instance: #ff9f0a;
|
|
43
|
+
--k-theorem: #a395e0;
|
|
44
|
+
--k-opaque: #ff6b3d;
|
|
45
|
+
--k-axiom: #ff375f;
|
|
46
|
+
/* a syntax extension command: syntax, notation, macro_rules, elab_rules (TCBSpec decision 2) */
|
|
47
|
+
--k-notation: #a2845e;
|
|
48
|
+
--k-external: #aeaeb2;
|
|
49
|
+
|
|
50
|
+
/* the Status scheme (decided 2026-10-08, CanvasSpec "Colour schemes"): one colour per point, the
|
|
51
|
+
most urgent state winning; Okabe and Ito's palette, which colour-blind readers tell apart, the
|
|
52
|
+
quiet states set apart by lightness and hue (not yet reviewed a light grey, trusted a pale
|
|
53
|
+
green, failed a dark grey; 2026-10-09). Commented is a calm
|
|
54
|
+
cobalt blue (2026-10-09), darker than building's sky blue and bluer than sorry's purple, so
|
|
55
|
+
that it stays apart from both, and from failed's grey, for every kind of colour blindness */
|
|
56
|
+
--status-failed: #4d4d52;
|
|
57
|
+
--status-building: #56b4e9;
|
|
58
|
+
--status-sorry: #cc79a7;
|
|
59
|
+
--status-commented: #2a62c0;
|
|
60
|
+
--status-stale: #e69f00;
|
|
61
|
+
--status-approved: #009e73;
|
|
62
|
+
--status-unreviewed: #c7c7cc;
|
|
63
|
+
--status-trusted: #b3e2c2;
|
|
64
|
+
|
|
65
|
+
--st-failed: #ff3b30;
|
|
66
|
+
--st-sorry: #ff9f0a;
|
|
67
|
+
--st-building: #0a84ff;
|
|
68
|
+
--st-stale: #8e8e93;
|
|
69
|
+
--st-ok: #30b158;
|
|
70
|
+
/* a review target's star */
|
|
71
|
+
--target-star: #f5b301;
|
|
72
|
+
--target-star-edge: rgba(255, 255, 255, 0.95);
|
|
73
|
+
/* a key declaration's diamond (ExportSpec decision 4): the star's family, a shade deeper */
|
|
74
|
+
--key-mark: #d99a00;
|
|
75
|
+
/* review status (ReviewSpec): what reviewers said about the present version; a comment in a calm
|
|
76
|
+
blue, which reads as something to read rather than an alarm */
|
|
77
|
+
--rv-approved: #2fb36b;
|
|
78
|
+
--rv-commented: #3d74d4;
|
|
79
|
+
--rv-stale: #f2a33a;
|
|
80
|
+
/* trusted without review (a prefix in the review's trusted list): nothing to review there */
|
|
81
|
+
--rv-trusted: #6f8db0;
|
|
82
|
+
/* what an agent advises where no reviewer said anything (AgentSpec): dashed, and quieter than a
|
|
83
|
+
review, a comment the heavier */
|
|
84
|
+
--rv-advice-approve: rgba(47, 179, 107, 0.62);
|
|
85
|
+
--rv-advice-comment: #4a72c4;
|
|
86
|
+
/* the review box's Approve and Comment, solid with white text (the owner's decision of
|
|
87
|
+
2026-10-12): the green and blue of what they record, a shade deeper, so that white reads on
|
|
88
|
+
them (4.5:1 and more) in either theme */
|
|
89
|
+
--rv-approve-btn: color-mix(in srgb, var(--rv-approved) 74%, black);
|
|
90
|
+
--rv-comment-btn: color-mix(in srgb, var(--rv-commented) 88%, black);
|
|
91
|
+
/* what is wrong or goes away: an error, a line removed, a count of what is new, a remove or
|
|
92
|
+
revoke button */
|
|
93
|
+
--bad: #e5484d;
|
|
94
|
+
--banner-bad: #c4161c;
|
|
95
|
+
--banner-warn: #a05a00;
|
|
96
|
+
--banner-info: #0a5fc4;
|
|
97
|
+
|
|
98
|
+
--tk-keyword: #ad3da4;
|
|
99
|
+
--tk-type: #3e7fd6;
|
|
100
|
+
--tk-comment: #8a8a8e;
|
|
101
|
+
--tk-string: #c4392b;
|
|
102
|
+
--tk-number: #6c5ce7;
|
|
103
|
+
--tk-attr: #b5762c;
|
|
104
|
+
--tk-op: #ad3da4;
|
|
105
|
+
/* a note on the board (web/src/sticky.ts): a surface of the page's own, as the canvas's menu and
|
|
106
|
+
the popovers are, marked by the accent (2026-10-09); in both themes from the theme's tokens */
|
|
107
|
+
--note-bg: color-mix(in srgb, var(--surface-solid) 94%, transparent);
|
|
108
|
+
--note-edge: var(--line);
|
|
109
|
+
--note-text: var(--text);
|
|
110
|
+
--note-mute: var(--text-2);
|
|
111
|
+
--note-icon: var(--accent);
|
|
112
|
+
/* a note's dot, zoomed out (the owner's decision, 2026-10-12), coloured by what it carries: a
|
|
113
|
+
note's in the accent, a paper's in the amber the reference window marks places in papers with, an
|
|
114
|
+
image's in a teal */
|
|
115
|
+
--note-paper: #d99a0f;
|
|
116
|
+
--note-image: #1a9c8a;
|
|
117
|
+
/* a past graph's marks (HistorySpec decision 17), as a diff colours them: gone now in red, new
|
|
118
|
+
since in green, another version now in amber, renamed since in teal; on the canvas they are
|
|
119
|
+
rings and outlines, so that they never pass for a point's own colour */
|
|
120
|
+
--tm-gone: #e0435a;
|
|
121
|
+
--tm-new: #2f9e64;
|
|
122
|
+
--tm-changed: #d27b00;
|
|
123
|
+
--tm-renamed: #0f97ab;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* dark: chosen, or following the system (web/src/theme.ts sets data-theme before the first paint) */
|
|
127
|
+
:root { color-scheme: light; }
|
|
128
|
+
:root[data-theme="dark"] {
|
|
129
|
+
color-scheme: dark;
|
|
130
|
+
--verified: #ab97ff;
|
|
131
|
+
--canvas: #0b0b0d;
|
|
132
|
+
--surface: rgba(28, 28, 30, 0.78);
|
|
133
|
+
--surface-solid: #1c1c1e;
|
|
134
|
+
--line: rgba(255, 255, 255, 0.09);
|
|
135
|
+
--text: #f5f5f7;
|
|
136
|
+
--text-2: #a1a1a6;
|
|
137
|
+
--text-3: #6e6e73;
|
|
138
|
+
--disc: rgba(255, 255, 255, 0.025);
|
|
139
|
+
--disc-line: rgba(255, 255, 255, 0.08);
|
|
140
|
+
--label: rgba(245, 245, 247, 0.5);
|
|
141
|
+
--shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 28px rgba(0, 0, 0, 0.45);
|
|
142
|
+
--shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.4), 0 22px 60px rgba(0, 0, 0, 0.6);
|
|
143
|
+
--code-bg: rgba(255, 255, 255, 0.05);
|
|
144
|
+
--edge-from: rgba(255, 169, 77, 0.7);
|
|
145
|
+
--edge-to: rgba(116, 143, 252, 0.7);
|
|
146
|
+
--target-star-edge: rgba(0, 0, 0, 0.55);
|
|
147
|
+
--rv-trusted: #7f9cbf;
|
|
148
|
+
--rv-advice-approve: rgba(80, 200, 130, 0.55);
|
|
149
|
+
--rv-advice-comment: #8aaef0;
|
|
150
|
+
--k-theorem: #8b7fd0;
|
|
151
|
+
--k-notation: #b89b74;
|
|
152
|
+
--banner-bad: #ff7b72;
|
|
153
|
+
--banner-warn: #ffc56b;
|
|
154
|
+
--banner-info: #7ab8ff;
|
|
155
|
+
--k-external: #636366;
|
|
156
|
+
/* on the dark canvas the failed grey is lighter, so that it still shows, and the very light green
|
|
157
|
+
of trusted lighter still; not yet reviewed is a dim grey, darker than failed's, so that the two
|
|
158
|
+
greys never meet in lightness. Commented's blue is a step lighter too, so that it stands out of a dark cluster as
|
|
159
|
+
the other states do, and still darker than building's sky blue */
|
|
160
|
+
--status-failed: #77777c;
|
|
161
|
+
--status-commented: #3570d0;
|
|
162
|
+
--status-unreviewed: #4c4c52;
|
|
163
|
+
--status-trusted: rgba(170, 222, 187, 0.82);
|
|
164
|
+
--tk-keyword: #ff7ab2;
|
|
165
|
+
--tk-type: #6bdfff;
|
|
166
|
+
--tk-comment: #7f8c98;
|
|
167
|
+
--tk-string: #ff8170;
|
|
168
|
+
--tk-number: #d9c97c;
|
|
169
|
+
--tk-attr: #ffa14f;
|
|
170
|
+
--tk-op: #ff7ab2;
|
|
171
|
+
--tm-gone: #ff6b7d;
|
|
172
|
+
--tm-new: #4cc38a;
|
|
173
|
+
--tm-changed: #f5a524;
|
|
174
|
+
--tm-renamed: #38c9dc;
|
|
175
|
+
--note-paper: #f5b83d;
|
|
176
|
+
--note-image: #3cc7b1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
* { box-sizing: border-box; }
|
|
180
|
+
html, body { margin: 0; height: 100%; overflow: hidden; }
|
|
181
|
+
body {
|
|
182
|
+
background: var(--canvas);
|
|
183
|
+
color: var(--text);
|
|
184
|
+
font: 13px/1.45 var(--font);
|
|
185
|
+
-webkit-font-smoothing: antialiased;
|
|
186
|
+
}
|
|
187
|
+
button { font: inherit; color: inherit; cursor: pointer; }
|
|
188
|
+
|
|
189
|
+
#canvas { position: fixed; inset: 0; width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
|
|
190
|
+
#labels { position: fixed; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
|
|
191
|
+
#cards { position: fixed; inset: 0; pointer-events: none; overflow: hidden; }
|
|
192
|
+
|
|
193
|
+
.glass {
|
|
194
|
+
background: var(--surface);
|
|
195
|
+
backdrop-filter: saturate(180%) blur(22px);
|
|
196
|
+
-webkit-backdrop-filter: saturate(180%) blur(22px);
|
|
197
|
+
border: 0.5px solid var(--line);
|
|
198
|
+
box-shadow: var(--shadow);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.logo {
|
|
202
|
+
font-weight: 700;
|
|
203
|
+
letter-spacing: -0.02em;
|
|
204
|
+
background: var(--grad);
|
|
205
|
+
-webkit-background-clip: text;
|
|
206
|
+
background-clip: text;
|
|
207
|
+
color: transparent;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* ---------------------------------------------------------------- toolbar */
|
|
211
|
+
|
|
212
|
+
#bar {
|
|
213
|
+
position: fixed; top: 12px; left: 12px; right: 12px;
|
|
214
|
+
display: flex; align-items: center; gap: 14px;
|
|
215
|
+
height: 48px; padding: 0 10px 0 16px; border-radius: 16px; z-index: 20;
|
|
216
|
+
}
|
|
217
|
+
.brand { display: flex; align-items: baseline; gap: 10px; min-width: 0; flex: 1; }
|
|
218
|
+
/* back and forward: a pill of two chevrons, in the bar and in the source window */
|
|
219
|
+
.nav {
|
|
220
|
+
display: inline-flex; gap: 2px; align-self: center; flex: none; padding: 2px;
|
|
221
|
+
background: var(--code-bg); border: 0.5px solid var(--line); border-radius: 10px;
|
|
222
|
+
}
|
|
223
|
+
.nav button {
|
|
224
|
+
display: grid; place-items: center; width: 32px; height: 28px; padding: 0; border: 0;
|
|
225
|
+
border-radius: 8px; background: transparent; color: var(--text); cursor: pointer;
|
|
226
|
+
transition: background 0.15s, color 0.15s, box-shadow 0.15s;
|
|
227
|
+
}
|
|
228
|
+
.nav svg { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
|
|
229
|
+
.nav button:hover:not(:disabled) { background: var(--surface-solid); color: var(--accent); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); }
|
|
230
|
+
.nav button:active:not(:disabled) { transform: translateY(0.5px); }
|
|
231
|
+
.nav button:disabled { color: var(--text-3); opacity: 0.45; cursor: default; }
|
|
232
|
+
/* the review strip, one line of progress wherever the review has a focus, stays in the middle of
|
|
233
|
+
the canvas, between the side panel and the panel (--inset-left, --inset-right: main.ts), so that
|
|
234
|
+
it never covers either */
|
|
235
|
+
#lensbar {
|
|
236
|
+
position: fixed; top: 110px; left: calc((100vw + var(--inset-left, 0px) - var(--inset-right, 0px)) / 2); transform: translateX(-50%); z-index: 15;
|
|
237
|
+
display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 12px;
|
|
238
|
+
font-size: 12.5px; max-width: calc(100vw - var(--inset-left, 0px) - var(--inset-right, 0px) - 16px);
|
|
239
|
+
transition: left 0.32s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
240
|
+
}
|
|
241
|
+
@media (max-width: 900px) {
|
|
242
|
+
#lens-meta { display: none; }
|
|
243
|
+
#lensbar { left: 50%; max-width: calc(100vw - 32px); }
|
|
244
|
+
}
|
|
245
|
+
#lens-title { font: 600 12.5px var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
246
|
+
/* short of room, the counts give way before the name of what the review strip is on */
|
|
247
|
+
#lens-meta { color: var(--text-2); white-space: nowrap; flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
248
|
+
/* what agents comment on, in the strip's line: where people start (AgentSpec decision 6), advice
|
|
249
|
+
beside the counts; and the reader's own part done */
|
|
250
|
+
.lens-adv { color: var(--rv-advice-comment); font-weight: 600; }
|
|
251
|
+
.lens-adv .bot { margin-right: 3px; }
|
|
252
|
+
.lens-done { color: var(--rv-approved); font-weight: 600; }
|
|
253
|
+
.tk-ref { cursor: pointer; border-radius: 3px; }
|
|
254
|
+
|
|
255
|
+
/* ---------------------------------------------------------------- review (ReviewSpec) */
|
|
256
|
+
|
|
257
|
+
.rv { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
|
|
258
|
+
.rv-op { font-size: 12.5px; line-height: 1.45; }
|
|
259
|
+
.rv-op.old { opacity: 0.6; }
|
|
260
|
+
.rv-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; background: var(--text-3); vertical-align: 1px; }
|
|
261
|
+
.rv-op.rv-approve .rv-dot { background: var(--rv-approved); }
|
|
262
|
+
.rv-op.rv-comment .rv-dot { background: var(--rv-commented); }
|
|
263
|
+
.rv-op.old .rv-dot { background: var(--rv-stale); }
|
|
264
|
+
.rv-c { margin: 2px 0 0 14px; padding: 4px 8px; background: var(--code-bg); border-radius: 6px; white-space: pre-wrap; font-size: 12px; }
|
|
265
|
+
.rv-hist summary { cursor: pointer; color: var(--text-2); font-size: 12px; }
|
|
266
|
+
.rv-hist .rv-op { margin-left: 8px; }
|
|
267
|
+
/* comments read as light Markdown (ReviewSpec, "Comments"; web/src/markdown.ts): paragraphs keep the
|
|
268
|
+
writer's line breaks, quotes are ruled at the left — a quoted opinion's in the accent, its
|
|
269
|
+
attribution going back to it — and code is set as in the source window, a code quote under its
|
|
270
|
+
file and lines, which open the source there */
|
|
271
|
+
.md { white-space: normal; overflow-wrap: anywhere; }
|
|
272
|
+
.md > * + *, .md-q > * + *, .md-cq > * + * { margin-top: 5px; }
|
|
273
|
+
.md p { margin: 0; white-space: pre-wrap; }
|
|
274
|
+
.md code { font: 11.5px var(--mono); background: var(--code-bg); padding: 0 3px; border-radius: 4px; }
|
|
275
|
+
.md pre.md-code { margin: 0; padding: 6px 8px; border-radius: 6px; font: 11.5px/1.5 var(--mono); }
|
|
276
|
+
.rv-c .md-code, .rv-adv-c .md-code { background: var(--surface-solid); box-shadow: inset 0 0 0 1px var(--line); }
|
|
277
|
+
.md-q { margin: 0; padding: 1px 0 1px 9px; border-left: 2px solid var(--line); color: var(--text-2); }
|
|
278
|
+
.md-q.quoted { border-left-color: color-mix(in srgb, var(--accent) 55%, transparent); }
|
|
279
|
+
.md-ref, .md-op, .md-src {
|
|
280
|
+
border: 0; background: none; padding: 0; margin: 0; font: inherit; color: var(--accent); cursor: pointer; text-align: left;
|
|
281
|
+
}
|
|
282
|
+
.md-ref:hover, .md-op:hover, .md-src:hover { text-decoration: underline; }
|
|
283
|
+
.md-ref code { color: inherit; }
|
|
284
|
+
.md-by { display: block; font-size: 11.5px; }
|
|
285
|
+
.md-by b { font-weight: 600; }
|
|
286
|
+
.md-cq-h { display: block; font: 11px var(--mono); }
|
|
287
|
+
/* Quote: on each opinion with a comment, quiet until wanted */
|
|
288
|
+
.rv-quote {
|
|
289
|
+
margin-left: 4px; padding: 0 6px; border: 0; border-radius: 5px; background: none; color: var(--text-3);
|
|
290
|
+
font: 600 11px var(--font); line-height: 17px; cursor: pointer; vertical-align: 1px;
|
|
291
|
+
}
|
|
292
|
+
.rv-quote:hover, .rv-quote:focus-visible { color: var(--accent); background: var(--code-bg); }
|
|
293
|
+
/* a quoted opinion gone to, and quoted lines opened: flashed in the accent, then as they were */
|
|
294
|
+
@keyframes vp-flash { from { background-color: color-mix(in srgb, var(--accent) 24%, transparent); } to { background-color: transparent; } }
|
|
295
|
+
.rv-flash, .sw-win .ln.ln-flash { animation: vp-flash 2.4s ease-out; border-radius: 6px; }
|
|
296
|
+
@media (prefers-reduced-motion: reduce) { .rv-flash, .sw-win .ln.ln-flash { animation-duration: 4s; animation-timing-function: steps(1, end); } }
|
|
297
|
+
/* what changed since a stale opinion: under it, unfaded, removed lines red and added lines green
|
|
298
|
+
in both themes (a tint of the review colours over the surface, the marks mixed with the text) */
|
|
299
|
+
.rv-changes { margin: -2px 0 2px 14px; font-size: 12px; }
|
|
300
|
+
.rv-changes summary { cursor: pointer; color: var(--text-2); }
|
|
301
|
+
.rv-changes summary:hover { color: var(--text); }
|
|
302
|
+
.rv-n b { font-weight: 600; font-variant-numeric: tabular-nums; margin-left: 6px; }
|
|
303
|
+
.rv-n .add, .rv-delta .add::before { color: color-mix(in srgb, var(--rv-approved) 70%, var(--text)); }
|
|
304
|
+
.rv-n .del, .rv-delta .del::before { color: color-mix(in srgb, var(--bad) 75%, var(--text)); }
|
|
305
|
+
.rv-cmp { margin: 4px 0; line-height: 1.4; }
|
|
306
|
+
.rv-cmp.warn { color: var(--banner-warn); }
|
|
307
|
+
.rv-cmp code { font: 11px var(--mono); }
|
|
308
|
+
.rv-delta {
|
|
309
|
+
margin-top: 4px; padding: 4px 0; border-radius: 8px; background: var(--code-bg);
|
|
310
|
+
font: 11.5px/1.5 var(--mono); max-height: 50vh; overflow: auto;
|
|
311
|
+
}
|
|
312
|
+
.rv-delta .dl { display: grid; grid-template-columns: 16px 1fr; min-height: 1.5em; padding-right: 8px; }
|
|
313
|
+
.rv-delta .dl > span { white-space: pre-wrap; word-break: break-word; }
|
|
314
|
+
.rv-delta .dl::before { text-align: center; user-select: none; }
|
|
315
|
+
.rv-delta .del { background: color-mix(in srgb, var(--bad) 14%, transparent); }
|
|
316
|
+
.rv-delta .del::before { content: "−"; }
|
|
317
|
+
.rv-delta .add { background: color-mix(in srgb, var(--rv-approved) 16%, transparent); }
|
|
318
|
+
.rv-delta .add::before { content: "+"; }
|
|
319
|
+
.rv-delta .same::before { content: ""; }
|
|
320
|
+
.rv-delta .skip { display: block; padding-left: 16px; color: var(--text-2); font: italic 11px var(--font); }
|
|
321
|
+
.sw-review .rv-delta { max-height: none; }
|
|
322
|
+
.rv-who { display: flex; gap: 6px; }
|
|
323
|
+
.rv-who input, .rv-text {
|
|
324
|
+
flex: 1; font: 12.5px var(--font); color: var(--text); background: var(--surface-solid);
|
|
325
|
+
border: 1px solid var(--line); border-radius: 7px; padding: 5px 8px; resize: vertical;
|
|
326
|
+
}
|
|
327
|
+
/* a comment box: its lines wrap, so it never scrolls sideways; it grows as one writes
|
|
328
|
+
(web/src/reviewbox.ts, fitBox), from three lines, five in a source window (2026-10-10) */
|
|
329
|
+
.rv-text {
|
|
330
|
+
/* its own height, which a column's flex would take from it */
|
|
331
|
+
flex: none; box-sizing: border-box; width: 100%; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere;
|
|
332
|
+
overflow-x: hidden; overflow-y: auto; min-height: calc(3 * 1.45em + 12px); max-height: calc(18 * 1.45em + 12px);
|
|
333
|
+
}
|
|
334
|
+
.sw-review .rv-text { min-height: calc(5 * 1.45em + 12px); }
|
|
335
|
+
.rv-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
|
|
336
|
+
.rv-btn {
|
|
337
|
+
border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 12px var(--font);
|
|
338
|
+
padding: 4px 10px; border-radius: 7px; cursor: pointer;
|
|
339
|
+
}
|
|
340
|
+
.rv-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
|
|
341
|
+
/* a button that cannot be used here says why under the pointer, and looks it */
|
|
342
|
+
.rv-btn:disabled { color: var(--text-3); cursor: default; }
|
|
343
|
+
/* Approve and Comment, wherever the review box stands (the panel, a source window, an axiom's row):
|
|
344
|
+
solid, white on their colour, which a hover lightens and a press deepens; the focus is a ring of
|
|
345
|
+
their colour outside them, and a button that cannot be used is faded, never grey on colour */
|
|
346
|
+
.rv-btn.approve, .rv-btn.comment { color: white; font-weight: 500; border-color: transparent; }
|
|
347
|
+
.rv-btn.approve { background: var(--rv-approve-btn); }
|
|
348
|
+
.rv-btn.comment { background: var(--rv-comment-btn); }
|
|
349
|
+
.rv-btn.approve:hover:not(:disabled), .rv-btn.comment:hover:not(:disabled) { color: white; border-color: transparent; filter: brightness(1.12); }
|
|
350
|
+
.rv-btn.approve:active:not(:disabled), .rv-btn.comment:active:not(:disabled) { filter: brightness(0.92); }
|
|
351
|
+
.rv-btn.approve:focus-visible { outline: 2px solid var(--rv-approve-btn); outline-offset: 2px; }
|
|
352
|
+
.rv-btn.comment:focus-visible { outline: 2px solid var(--rv-comment-btn); outline-offset: 2px; }
|
|
353
|
+
/* on a dark surface the deeper shade is too dark a ring: the status colour itself shows */
|
|
354
|
+
:root[data-theme="dark"] .rv-btn.approve:focus-visible { outline-color: var(--rv-approved); }
|
|
355
|
+
:root[data-theme="dark"] .rv-btn.comment:focus-visible { outline-color: var(--rv-commented); }
|
|
356
|
+
.rv-btn.approve:disabled, .rv-btn.comment:disabled { color: white; opacity: 0.45; }
|
|
357
|
+
.rv-btn.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
|
|
358
|
+
.rv-tgt { align-self: flex-start; }
|
|
359
|
+
.rv-tag { font-size: 12px; color: var(--accent); }
|
|
360
|
+
.rv-as { font-size: 11.5px; margin-left: auto; }
|
|
361
|
+
.rv-err { color: var(--bad); font-size: 12px; }
|
|
362
|
+
.rv-target { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; background: var(--code-bg); border-radius: 10px; }
|
|
363
|
+
.rv-prog { font-size: 12.5px; }
|
|
364
|
+
.rv-prog .commented { color: var(--rv-commented); }
|
|
365
|
+
.rv-bar { display: flex; height: 5px; border-radius: 3px; overflow: hidden; background: var(--line); min-width: 40px; }
|
|
366
|
+
.rv-bar i { display: block; height: 100%; }
|
|
367
|
+
.rv-bar i.ok { background: var(--rv-approved); }
|
|
368
|
+
.rv-bar i.commented { background: var(--rv-commented); }
|
|
369
|
+
.rv-bar i.stale { background: var(--rv-stale); }
|
|
370
|
+
.rv-diff-h { margin-top: 4px; font-weight: 600; }
|
|
371
|
+
/* a definition's review status in the TCB list */
|
|
372
|
+
.row.rv-approved::before, .row.rv-commented::before, .row.rv-stale::before {
|
|
373
|
+
content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: 1px;
|
|
374
|
+
}
|
|
375
|
+
.row.rv-approved::before { background: var(--rv-approved); }
|
|
376
|
+
.row.rv-commented::before { background: var(--rv-commented); }
|
|
377
|
+
.row.rv-stale::before { background: var(--rv-stale); }
|
|
378
|
+
/* trusted without review: a hollow mark, nothing to do */
|
|
379
|
+
.row.rv-trusted::before {
|
|
380
|
+
content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: 1px;
|
|
381
|
+
box-shadow: inset 0 0 0 1.5px var(--rv-trusted);
|
|
382
|
+
}
|
|
383
|
+
.row.rv-trusted { color: var(--text-2); }
|
|
384
|
+
.rv-trusted-by code { font: 11px var(--mono); }
|
|
385
|
+
|
|
386
|
+
.star { color: var(--target-star); margin-right: 4px; }
|
|
387
|
+
|
|
388
|
+
/* what is trusted without review (web/src/trust.ts): the list, the outline's shields, the question */
|
|
389
|
+
/* what is trusted without review: the review's, the same on every board, in a popover from the side
|
|
390
|
+
panel's Trusted button */
|
|
391
|
+
#trust-list { display: flex; flex-direction: column; gap: 8px; }
|
|
392
|
+
.tl-h { display: flex; flex-direction: column; gap: 1px; font-size: 11px; }
|
|
393
|
+
.tl-t { font: 600 12.5px var(--font); color: var(--text); }
|
|
394
|
+
.tl-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
395
|
+
.tl-chip {
|
|
396
|
+
display: inline-flex; align-items: center; max-width: 100%; height: 22px; border-radius: 6px;
|
|
397
|
+
border: 1px solid var(--line); background: var(--surface-solid);
|
|
398
|
+
}
|
|
399
|
+
.tl-chip.own { border-color: color-mix(in srgb, var(--rv-trusted) 55%, transparent); }
|
|
400
|
+
.tl-chip.off { border-style: dashed; background: transparent; }
|
|
401
|
+
/* the outside world as a whole: words, not a prefix */
|
|
402
|
+
.tl-chip.world .tl-name { font-family: var(--font); }
|
|
403
|
+
.tl-name {
|
|
404
|
+
border: 0; background: transparent; padding: 0 7px; font: 11.5px var(--mono); color: var(--text);
|
|
405
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
|
|
406
|
+
}
|
|
407
|
+
.tl-chip.off .tl-name { color: var(--text-3); text-decoration: line-through; }
|
|
408
|
+
.tl-x { border: 0; background: transparent; width: 18px; padding: 0 4px 0 0; flex: none; color: var(--text-3); font-size: 10px; }
|
|
409
|
+
.tl-x:hover { color: var(--bad); }
|
|
410
|
+
.tl-chip.off .tl-x { font-size: 13px; }
|
|
411
|
+
.tl-chip.off .tl-x:hover { color: var(--accent); }
|
|
412
|
+
/* the defaults are rarely taken off: their ✕ waits for the pointer */
|
|
413
|
+
.tl-chip:not(.own):not(.off):not(:hover):not(:focus-within) .tl-x { visibility: hidden; }
|
|
414
|
+
.tl-hint { font-size: 11px; line-height: 1.4; }
|
|
415
|
+
.tl-all {
|
|
416
|
+
align-self: flex-start; height: 24px; padding: 0 9px; border-radius: 7px; border: 1px dashed var(--line);
|
|
417
|
+
background: transparent; color: var(--text-2); font: 500 11.5px var(--font); cursor: pointer;
|
|
418
|
+
}
|
|
419
|
+
.tl-all:hover { border-color: var(--rv-trusted); color: var(--text); }
|
|
420
|
+
.tl-shield svg, .o-trust svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; vertical-align: -2px; }
|
|
421
|
+
.o-trust {
|
|
422
|
+
display: grid; place-items: center; flex: none; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 5px;
|
|
423
|
+
background: transparent; color: var(--text-3);
|
|
424
|
+
}
|
|
425
|
+
button.o-trust:hover { color: var(--accent); background: var(--code-bg); }
|
|
426
|
+
.o-trust.on { color: var(--rv-trusted); }
|
|
427
|
+
.o-trust.on svg { fill: color-mix(in srgb, var(--rv-trusted) 35%, transparent); }
|
|
428
|
+
.o-trust.under { opacity: 0.55; }
|
|
429
|
+
/* the action shows on the row under the pointer, or with the keyboard on it; a mark stays */
|
|
430
|
+
.o-row:not(:hover) button.o-trust:not(.on):not(:focus-visible) { visibility: hidden; }
|
|
431
|
+
/* hiding a level (ViewSpec decision 24): on the row under the pointer, as trusting is */
|
|
432
|
+
.o-hide {
|
|
433
|
+
display: grid; place-items: center; flex: none; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 5px;
|
|
434
|
+
background: transparent; color: var(--text-3);
|
|
435
|
+
}
|
|
436
|
+
.o-hide svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
|
|
437
|
+
.o-hide:hover { color: var(--accent); background: var(--code-bg); }
|
|
438
|
+
.o-row:not(:hover) .o-hide:not(:focus-visible) { visibility: hidden; }
|
|
439
|
+
/* a popover lies above the floating windows (#windows) */
|
|
440
|
+
#trust-pop {
|
|
441
|
+
position: fixed; z-index: 36; width: min(340px, calc(100vw - 24px)); border-radius: 14px; padding: 14px 16px 12px;
|
|
442
|
+
display: flex; flex-direction: column; gap: 8px; box-shadow: var(--shadow-lg);
|
|
443
|
+
}
|
|
444
|
+
.tp-title { font-weight: 600; font-size: 13.5px; word-break: break-word; }
|
|
445
|
+
.tp-title code, .tp-text code { font: 12px var(--mono); }
|
|
446
|
+
.tp-text { color: var(--text-2); font-size: 12.5px; line-height: 1.45; }
|
|
447
|
+
.tp-effect { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px; border-radius: 8px; background: var(--code-bg); font-size: 12px; }
|
|
448
|
+
.tp-effect b { font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
449
|
+
.tp-note { font-size: 11.5px; line-height: 1.4; }
|
|
450
|
+
.card.target .card-name::before { content: "★ "; color: var(--target-star); }
|
|
451
|
+
.rv-tgt.on { color: var(--target-star); border-color: color-mix(in srgb, var(--target-star) 55%, transparent); }
|
|
452
|
+
/* key declarations (ExportSpec decision 4): a diamond in the star's family, wherever they are listed */
|
|
453
|
+
.key-mark { color: var(--key-mark); margin-right: 3px; font-size: 0.9em; }
|
|
454
|
+
.card.key .card-name::before { content: "◆ "; color: var(--key-mark); }
|
|
455
|
+
.rv-key { align-self: flex-start; }
|
|
456
|
+
.rv-key.on { color: var(--key-mark); border-color: color-mix(in srgb, var(--key-mark) 55%, transparent); }
|
|
457
|
+
.rv-key-tag { color: var(--key-mark); }
|
|
458
|
+
.rv-keyprog .key-mark { margin-right: 1px; }
|
|
459
|
+
.lens-key { white-space: nowrap; }
|
|
460
|
+
.q-row.q-key { font-weight: 500; }
|
|
461
|
+
.q-row .key-mark { margin-right: 2px; }
|
|
462
|
+
.sb-btn.sb-key:not(:disabled) { color: var(--key-mark); }
|
|
463
|
+
|
|
464
|
+
/* the review wherever it has a focus (web/src/reviewqueue.ts): the strip, why a declaration is in
|
|
465
|
+
the TCB, and the TCB in review order */
|
|
466
|
+
/* short of room, "Reviewing" gives way before the target's name */
|
|
467
|
+
#lensbar.reviewing #lens-title { display: flex; align-items: baseline; min-width: 0; }
|
|
468
|
+
.lens-rv { font: 12.5px var(--font); color: var(--text-2); margin-right: 2px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
469
|
+
.lens-target { flex: none; border: 0; background: transparent; padding: 1px 4px; border-radius: 6px; font: inherit; color: var(--text); cursor: pointer; }
|
|
470
|
+
.lens-target:hover { background: var(--code-bg); color: var(--accent); }
|
|
471
|
+
.lens-target .star, .why .star, .q-row .star { margin-right: 2px; }
|
|
472
|
+
.why { margin: 0 0 12px; padding: 8px 10px; background: var(--code-bg); border-radius: 10px; font-size: 12px; }
|
|
473
|
+
.why-h { color: var(--text-2); margin-bottom: 4px; }
|
|
474
|
+
.why-chain { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px; font: 11.5px/1.6 var(--mono); }
|
|
475
|
+
.why-step { border: 0; background: transparent; padding: 0 3px; border-radius: 5px; font: inherit; color: var(--accent); cursor: pointer; }
|
|
476
|
+
.why-step:hover { background: var(--surface-solid); }
|
|
477
|
+
.why-h .why-step { font: 600 12px var(--mono); color: var(--text); }
|
|
478
|
+
.why-step.here { color: var(--text); font-weight: 600; }
|
|
479
|
+
.why-arrow { color: var(--text-3); cursor: help; }
|
|
480
|
+
.sec-tcb { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
|
|
481
|
+
.sec-tcb .seg { margin-left: auto; }
|
|
482
|
+
.seg.mini { padding: 2px; border-radius: 8px; }
|
|
483
|
+
.seg.mini button { padding: 2px 8px; border-radius: 6px; font-size: 11.5px; }
|
|
484
|
+
.q-note { font-size: 11.5px; margin: -2px 0 6px; }
|
|
485
|
+
.q-row .q-n { display: inline-block; min-width: 2.2em; margin-right: 6px; text-align: right; color: var(--text-3); font-variant-numeric: tabular-nums; }
|
|
486
|
+
/* every row of the queue has its dot, so that the numbers line up: an open one for none yet */
|
|
487
|
+
.q-row.rv-none::before {
|
|
488
|
+
content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: 1px;
|
|
489
|
+
box-shadow: inset 0 0 0 1px var(--text-3);
|
|
490
|
+
}
|
|
491
|
+
.q-row.q-mine { opacity: 0.5; }
|
|
492
|
+
|
|
493
|
+
/* the floating windows (web/src/floatwin.ts): one layer over the page, under the hover cards, the
|
|
494
|
+
popovers and the modal windows; in it, the window pressed or focused last in front */
|
|
495
|
+
#windows { position: fixed; inset: 0; z-index: 35; pointer-events: none; }
|
|
496
|
+
#windows > * { pointer-events: auto; }
|
|
497
|
+
/* a popover lies above the windows: it was opened last, and goes on a press anywhere else. Those
|
|
498
|
+
inside a bar raise the bar with them while they are open */
|
|
499
|
+
#bar:has(#share-pop:not([hidden]), #results:not([hidden]), #who-menu:not([hidden])), #viewbar:has(#views-menu:not([hidden]), #focus-menu:not([hidden])), #zoom:has(#eyes-pop:not([hidden])) { z-index: 36; }
|
|
500
|
+
/* a source window (web/src/sourcewin.ts): floating, not modal; as large as its code needs until the
|
|
501
|
+
reader moves or resizes it (floatwin.ts sets its place, and its bounds while it is fitted to its
|
|
502
|
+
code), scrolling down beyond that */
|
|
503
|
+
.sw-win {
|
|
504
|
+
position: fixed; display: flex; flex-direction: column; border-radius: 14px; background: var(--surface-solid);
|
|
505
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
506
|
+
}
|
|
507
|
+
.sw-win:focus { outline: none; }
|
|
508
|
+
/* it appears at the size its code gives it (sourcewin.ts, awaitCode): a new window waits unseen while
|
|
509
|
+
its code is read, and the reference window paired beside it waits with it (paperwin.ts, dock) */
|
|
510
|
+
.sw-win.opening, .pw-win.waiting { visibility: hidden; }
|
|
511
|
+
/* a reading longer than a moment, said over the frame before, which keeps its size: placed out of
|
|
512
|
+
the flow, it takes no room of the window's */
|
|
513
|
+
.sw-win.slow::after {
|
|
514
|
+
content: "Reading the source…"; position: absolute; top: 44px; right: 16px; z-index: 3; padding: 2px 10px;
|
|
515
|
+
border-radius: 999px; background: var(--surface-solid); box-shadow: 0 0 0 1px var(--line); color: var(--text-2);
|
|
516
|
+
font: 12px var(--font); pointer-events: none;
|
|
517
|
+
}
|
|
518
|
+
.sw-win.moving, .sw-win.sizing { user-select: none; -webkit-user-select: none; }
|
|
519
|
+
/* clipped, never scrolled: a control revealed by the browser must not shift the window's content */
|
|
520
|
+
.sw-box { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; border-radius: inherit; overflow: hidden; overflow: clip; }
|
|
521
|
+
/* its title bar: dragged to move it, double-clicked to collapse it */
|
|
522
|
+
.sw-head {
|
|
523
|
+
display: flex; align-items: baseline; gap: 10px; padding: 8px 8px 7px 12px; border-bottom: 1px solid var(--line);
|
|
524
|
+
cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none;
|
|
525
|
+
}
|
|
526
|
+
.sw-win.moving .sw-head { cursor: grabbing; }
|
|
527
|
+
.sw-head .nav { margin-right: 2px; }
|
|
528
|
+
/* under the title bar, why the pairing opened no reference beside it (AttachmentSpec decision 8) */
|
|
529
|
+
.sw-pair { padding: 5px 12px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--text-2); }
|
|
530
|
+
/* a narrow window shortens the namespace and the place, never its buttons */
|
|
531
|
+
.sw-name { font: 600 15px var(--font); flex: none; }
|
|
532
|
+
.sw-ns { color: var(--text-2); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 40vw; min-width: 0; }
|
|
533
|
+
.sw-loc { color: var(--text-3); font: 11.5px var(--mono); margin-left: auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
534
|
+
.sw-acts { display: inline-flex; align-items: center; gap: 2px; align-self: center; flex: none; }
|
|
535
|
+
.sw-acts .icon, .sw-pill .icon {
|
|
536
|
+
display: inline-grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--text-2);
|
|
537
|
+
width: 26px; height: 26px; border-radius: 7px; cursor: pointer; font-size: 14px;
|
|
538
|
+
}
|
|
539
|
+
.sw-acts .icon:hover, .sw-pill .icon:hover { background: var(--code-bg); color: var(--text); }
|
|
540
|
+
.sw-acts svg, .sw-pill svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
|
541
|
+
/* pinned: the pin filled in the accent, and a line of it over the title bar, so that a pinned window
|
|
542
|
+
reads apart from the one that follows the selection */
|
|
543
|
+
.sw-pinned { display: inline-grid; place-items: center; flex: none; width: 26px; height: 26px; color: var(--accent); }
|
|
544
|
+
.sw-pinned svg { fill: color-mix(in srgb, var(--accent) 35%, transparent); }
|
|
545
|
+
.sw-win.pinned .sw-head { box-shadow: inset 0 2px 0 var(--accent); }
|
|
546
|
+
.sw-win:not(.collapsed) > .fl-rz { display: block; position: absolute; z-index: 2; touch-action: none; }
|
|
547
|
+
.sw-box > .banner { margin: 8px 16px 0; }
|
|
548
|
+
/* collapsed: a pill with its declaration's name; a click opens it again */
|
|
549
|
+
.sw-pill { display: none; }
|
|
550
|
+
.sw-win.collapsed { border-radius: 999px; }
|
|
551
|
+
.sw-win.collapsed > .sw-box { display: none; }
|
|
552
|
+
.sw-win.collapsed > .sw-pill { display: flex; align-items: center; gap: 2px; min-width: 0; padding-right: 4px; }
|
|
553
|
+
.sw-pill-open {
|
|
554
|
+
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 6px 6px 6px 12px; border: 0;
|
|
555
|
+
border-radius: 999px; background: transparent; color: var(--text); font: 600 12.5px var(--font); text-align: left; cursor: pointer;
|
|
556
|
+
}
|
|
557
|
+
.sw-pill-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
558
|
+
.sw-pill .sw-pinned { width: 16px; height: 16px; }
|
|
559
|
+
/* the source and its review scroll together, under one scrollbar, and nothing scrolls sideways:
|
|
560
|
+
long lines wrap to the window's width (decided 2026-10-09), a name too long for a line broken
|
|
561
|
+
anywhere */
|
|
562
|
+
.sw-scroll { overflow-y: auto; overflow-x: hidden; flex: 1 1 auto; min-height: 60px; }
|
|
563
|
+
.sw-body { padding: 12px 16px; position: relative; }
|
|
564
|
+
/* text selected in the code: a small button at the right edge, under the selection's last line,
|
|
565
|
+
quotes those lines into the comment below (hover cards stand aside meanwhile) */
|
|
566
|
+
.sw-quote {
|
|
567
|
+
position: absolute; right: 12px; z-index: 1; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--line);
|
|
568
|
+
background: var(--surface-solid); color: var(--accent); font: 600 11.5px var(--font); line-height: 18px;
|
|
569
|
+
box-shadow: var(--shadow); cursor: pointer; white-space: nowrap; user-select: none; -webkit-user-select: none;
|
|
570
|
+
}
|
|
571
|
+
.sw-quote:hover { border-color: var(--accent); }
|
|
572
|
+
.sw-body pre.src {
|
|
573
|
+
margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font: 12.5px/1.55 var(--mono); background: transparent; padding: 0;
|
|
574
|
+
max-height: none; overflow: visible;
|
|
575
|
+
}
|
|
576
|
+
/* a line of code (web/src/highlight.ts, highlightLines): wrapped, its continuations hang under its
|
|
577
|
+
own indentation (--in, in characters) and four characters more, so that they read as the
|
|
578
|
+
same line going on; its first line starts where it would anyway */
|
|
579
|
+
.sw-win .ln { display: block; padding-left: calc((var(--in, 0) + 4) * 1ch); text-indent: calc((var(--in, 0) + 4) * -1ch); }
|
|
580
|
+
.sw-none { color: var(--text-2); font-size: 13px; padding: 8px 0; }
|
|
581
|
+
.sw-review { border-top: 1px solid var(--line); padding: 10px 16px 12px; }
|
|
582
|
+
.sw-review .sec { margin-top: 0; }
|
|
583
|
+
|
|
584
|
+
/* what Lean says is under the pointer, in the source window (as VS Code shows it) */
|
|
585
|
+
/* hover cards (web/src/hovercards.ts): the pointer can move onto them; a name in one opens the next */
|
|
586
|
+
.hcard {
|
|
587
|
+
position: fixed; left: 0; top: 0; z-index: 37; max-width: min(640px, calc(100vw - 16px)); max-height: 50vh;
|
|
588
|
+
overflow: auto; overscroll-behavior: contain; padding: 6px 10px; border-radius: 9px; background: var(--surface-solid);
|
|
589
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg); font-size: 12.5px; line-height: 1.45;
|
|
590
|
+
}
|
|
591
|
+
.hcard pre.code { margin: 2px 0; padding: 0; background: transparent; white-space: pre-wrap; font: 12px/1.5 var(--mono); }
|
|
592
|
+
.hcard hr { border: 0; border-top: 1px solid var(--line); margin: 6px 0; }
|
|
593
|
+
.hcard p { margin: 4px 0; }
|
|
594
|
+
.hcard code { font: 11.5px var(--mono); background: var(--code-bg); padding: 0 3px; border-radius: 4px; }
|
|
595
|
+
.hcard .tk-ref { text-decoration: underline dotted color-mix(in srgb, currentColor 45%, transparent); text-underline-offset: 2px; }
|
|
596
|
+
.hcard .tk-ref:hover { text-decoration: underline; }
|
|
597
|
+
.hc-where { display: flex; align-items: center; gap: 6px; color: var(--text-2); font-size: 11.5px; margin-bottom: 2px; }
|
|
598
|
+
.hc-where .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
|
|
599
|
+
.sw-tip-wait { color: var(--text-2); font-style: italic; }
|
|
600
|
+
.sw-tip-err { color: var(--bad); font-size: 12px; margin-top: 4px; }
|
|
601
|
+
|
|
602
|
+
/* the reference window (AttachmentSpec decision 11; web/src/paperwin.ts, paperview.ts): a window of
|
|
603
|
+
the page like the source window, beside it while paired; a PDF's pages drawn by pdf.js on a quiet
|
|
604
|
+
ground, each a sheet, the links lit on them and their subjects in the margin */
|
|
605
|
+
.pw-win {
|
|
606
|
+
position: fixed; display: flex; flex-direction: column; border-radius: 14px; background: var(--surface-solid);
|
|
607
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg); --pw-link: #e8a317; --pw-lit: #7d5cf0;
|
|
608
|
+
}
|
|
609
|
+
:root[data-theme="dark"] .pw-win { --pw-link: #f5b83d; --pw-lit: #a995ff; }
|
|
610
|
+
.pw-win:focus { outline: none; }
|
|
611
|
+
.pw-win.moving, .pw-win.sizing { user-select: none; -webkit-user-select: none; }
|
|
612
|
+
.pw-win:not(.collapsed) > .fl-rz { display: block; position: absolute; z-index: 3; touch-action: none; }
|
|
613
|
+
.pw-box { position: relative; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; border-radius: inherit; overflow: hidden; overflow: clip; }
|
|
614
|
+
.pw-head {
|
|
615
|
+
display: flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; border-bottom: 1px solid var(--line);
|
|
616
|
+
cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none; min-width: 0;
|
|
617
|
+
}
|
|
618
|
+
.pw-win.moving .pw-head { cursor: grabbing; }
|
|
619
|
+
.pw-title { font: 600 13.5px var(--font); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
620
|
+
.pw-pageno { color: var(--text-3); font: 11.5px var(--mono); white-space: nowrap; flex: none; }
|
|
621
|
+
.pw-acts { display: inline-flex; align-items: center; gap: 1px; margin-left: auto; flex: none; }
|
|
622
|
+
.pw-acts .icon, .pw-pill .icon, .pw-find .icon {
|
|
623
|
+
display: inline-grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--text-2);
|
|
624
|
+
width: 26px; height: 26px; border-radius: 7px; cursor: pointer; font-size: 14px;
|
|
625
|
+
}
|
|
626
|
+
.pw-acts .icon:hover, .pw-pill .icon:hover, .pw-find .icon:hover { background: var(--code-bg); color: var(--text); }
|
|
627
|
+
/* the box tool armed: its button pressed until the drag it is for */
|
|
628
|
+
.pw-acts .icon.on, .pw-acts .icon.on:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
629
|
+
.pw-acts svg, .pw-pill svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
|
630
|
+
.pw-find { display: flex; align-items: center; gap: 4px; padding: 5px 10px; border-bottom: 1px solid var(--line); }
|
|
631
|
+
.pw-find input { flex: 1; min-width: 0; height: 26px; border: 1px solid var(--line); border-radius: 7px; padding: 0 8px; background: var(--code-bg); color: var(--text); font: 12.5px var(--font); }
|
|
632
|
+
.pw-found { color: var(--text-2); font-size: 12px; white-space: nowrap; min-width: 54px; text-align: right; }
|
|
633
|
+
.pw-info { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px 12px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--text-2); }
|
|
634
|
+
.pw-info b { color: var(--text); font-weight: 600; }
|
|
635
|
+
.pw-info .rv-btn { padding: 2px 8px; font-size: 11.5px; }
|
|
636
|
+
.pw-note { color: var(--text-2); font-style: italic; }
|
|
637
|
+
.pw-linking { color: var(--text); }
|
|
638
|
+
.pw-others { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; }
|
|
639
|
+
.pw-chip { border: 1px solid var(--line); background: var(--surface-solid); border-radius: 999px; padding: 1px 8px; font-size: 11.5px; color: var(--text); max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
640
|
+
.pw-chip:hover, .pw-chip.on { border-color: var(--pw-lit); color: var(--pw-lit); }
|
|
641
|
+
.pw-host { position: relative; flex: 1 1 auto; min-height: 0; display: flex; background: color-mix(in srgb, var(--canvas) 70%, var(--surface-solid)); }
|
|
642
|
+
.pw-wait { margin: auto; color: var(--text-2); font-size: 13px; padding: 20px; text-align: center; }
|
|
643
|
+
.pw-missing { margin: auto; max-width: 440px; padding: 20px; font-size: 13px; color: var(--text-2); }
|
|
644
|
+
.pw-missing b { color: var(--text); }
|
|
645
|
+
.pw-missing code { font: 11.5px var(--mono); }
|
|
646
|
+
.pw-add { display: inline-block; cursor: pointer; margin-right: 8px; }
|
|
647
|
+
.pw-fill-why { font-size: 12px; color: var(--banner-warn); }
|
|
648
|
+
.pw-scroll { position: relative; flex: 1 1 auto; min-height: 0; overflow: auto; }
|
|
649
|
+
.pw-pdf { padding: 12px 0; }
|
|
650
|
+
/* a page: a white sheet whatever the theme (a paper is printed on white); its words are the text to
|
|
651
|
+
select, nothing else on it is; with the box tool armed, a drag on it draws a box */
|
|
652
|
+
.pw-page { position: relative; margin: 0 auto 12px; background: #fff; box-shadow: 0 0 0 1px var(--line), 0 2px 8px rgba(0, 0, 0, 0.12); cursor: default; user-select: none; -webkit-user-select: none; }
|
|
653
|
+
/* the page's words, the server's, laid over its picture: transparent, each at its word's box, its
|
|
654
|
+
letters as tall as the box and stretched across it (web/src/paperwords.ts); under the
|
|
655
|
+
selection's boxes, the search's matches and the links */
|
|
656
|
+
.pw-words { position: absolute; inset: 0; z-index: 0; overflow: hidden; line-height: 1; user-select: text; -webkit-user-select: text; }
|
|
657
|
+
.pw-words > span { position: absolute; white-space: pre; color: transparent; font-family: sans-serif; transform-origin: 0 0; cursor: text; }
|
|
658
|
+
/* the selection is lit as a search's matches are, a box a line over the page's own letters, in the
|
|
659
|
+
browser's colour (web/src/paperview.ts, drawSelection); the browser's own drawing of it, a box a
|
|
660
|
+
span with seams between, is hidden, and so are the layer's letters, which a browser would draw in
|
|
661
|
+
its selected text's colour */
|
|
662
|
+
.pw-words > span::selection { color: transparent; background: transparent; }
|
|
663
|
+
.pw-sel { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
|
|
664
|
+
.pw-selbox { position: absolute; background: rgba(0, 110, 255, 0.3); background: color-mix(in srgb, Highlight 45%, transparent); mix-blend-mode: multiply; border-radius: 1px; }
|
|
665
|
+
/* a link's region lets presses through to the words; the cursor says it is there */
|
|
666
|
+
.pw-page .pw-mark { pointer-events: none; }
|
|
667
|
+
.pw-page.on-link, .pw-page.on-link .pw-words > span { cursor: pointer; }
|
|
668
|
+
.pw-win.boxing .pw-page, .pw-win.boxing .pw-page .pw-words > span, .pw-win.boxing .pw-image { cursor: crosshair; }
|
|
669
|
+
/* what is drawn on a page is drawn on white paper in both themes: the light palette's colours */
|
|
670
|
+
.pw-page, .pw-stage { --pw-link: #e8a317; --pw-lit: #7d5cf0; }
|
|
671
|
+
.pw-canvas { position: absolute; inset: 0; display: block; }
|
|
672
|
+
.pw-num { position: absolute; left: 0; top: -11px; font: 9.5px/1 var(--mono); color: var(--text-3); user-select: none; }
|
|
673
|
+
.pw-marks { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
|
|
674
|
+
.pw-mark { position: absolute; pointer-events: auto; cursor: pointer; border-radius: 2px; }
|
|
675
|
+
.pw-mark.quote { background: color-mix(in srgb, var(--pw-link) 22%, transparent); mix-blend-mode: multiply; }
|
|
676
|
+
.pw-mark.region { border: 1.5px solid color-mix(in srgb, var(--pw-link) 70%, transparent); background: color-mix(in srgb, var(--pw-link) 6%, transparent); border-radius: 3px; }
|
|
677
|
+
.pw-mark.lit.quote { background: color-mix(in srgb, var(--pw-lit) 30%, transparent); box-shadow: 0 1.5px 0 var(--pw-lit); animation: pw-flash 1.4s ease-out 1; }
|
|
678
|
+
.pw-mark.lit.region { border: 2px solid var(--pw-lit); background: color-mix(in srgb, var(--pw-lit) 8%, transparent); animation: pw-flash 1.4s ease-out 1; }
|
|
679
|
+
/* the clip a note carries, opened from the note: lit, dashed as a note's own is, and no link */
|
|
680
|
+
.pw-mark.region.clip { border-style: dashed; cursor: default; }
|
|
681
|
+
@keyframes pw-flash { 0% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--pw-lit) 45%, transparent); } 100% { box-shadow: 0 0 0 0 transparent; } }
|
|
682
|
+
/* a search's matches, boxes of the server's words over the page; the one shown outlined */
|
|
683
|
+
.pw-hits { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
|
|
684
|
+
.pw-hit { position: absolute; background: rgba(255, 213, 0, 0.38); border-radius: 2px; mix-blend-mode: multiply; }
|
|
685
|
+
.pw-hit.on { background: rgba(255, 170, 0, 0.55); box-shadow: 0 0 0 1.5px #e07b00; }
|
|
686
|
+
.pw-drag { position: absolute; border: 1.5px dashed var(--pw-lit); background: color-mix(in srgb, var(--pw-lit) 10%, transparent); z-index: 3; pointer-events: none; border-radius: 2px; }
|
|
687
|
+
/* the margin: the subjects linked to places on the page, each a small tag at the right edge at the
|
|
688
|
+
height of its place; a click goes there on the board */
|
|
689
|
+
.pw-margin { position: absolute; top: 0; bottom: 0; right: 0; width: 12%; z-index: 4; pointer-events: none; }
|
|
690
|
+
.pw-marker {
|
|
691
|
+
position: absolute; right: 4px; transform: translateY(-2px); max-width: calc(100% - 6px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; pointer-events: auto;
|
|
692
|
+
border: 1px solid color-mix(in srgb, var(--pw-link) 60%, transparent); background: color-mix(in srgb, #fff 88%, var(--pw-link));
|
|
693
|
+
color: #5a4206; font: 600 10.5px var(--font); padding: 1px 6px; border-radius: 999px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18); cursor: pointer;
|
|
694
|
+
}
|
|
695
|
+
.pw-marker::before { content: "↩ "; opacity: 0.6; }
|
|
696
|
+
.pw-marker.lit { border-color: var(--pw-lit); color: #3f2aa0; background: color-mix(in srgb, #fff 86%, var(--pw-lit)); }
|
|
697
|
+
.pw-marker:hover { max-width: 360px; z-index: 1; }
|
|
698
|
+
/* an image, zoomed and moved as the canvas is; a drag moves it, and draws a box with the tool armed */
|
|
699
|
+
.pw-image { overflow: hidden; cursor: grab; touch-action: none; }
|
|
700
|
+
.pw-image.panning { cursor: grabbing; }
|
|
701
|
+
.pw-stage { position: absolute; left: 0; top: 0; transform-origin: 0 0; background: #fff; box-shadow: 0 0 0 1px var(--line), 0 2px 8px rgba(0, 0, 0, 0.12); }
|
|
702
|
+
.pw-img { display: block; width: 100%; height: 100%; user-select: none; -webkit-user-drag: none; }
|
|
703
|
+
/* what to do with what was picked: Link to …, under a label */
|
|
704
|
+
.pw-pick {
|
|
705
|
+
position: absolute; z-index: 6; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 6px; border-radius: 10px;
|
|
706
|
+
background: var(--surface-solid); box-shadow: 0 0 0 1px var(--line), var(--shadow); max-width: calc(100% - 16px);
|
|
707
|
+
}
|
|
708
|
+
/* the label takes a line of its own where the window is too narrow for it beside the buttons */
|
|
709
|
+
.pw-label { flex: 1 1 200px; width: 200px; min-width: 160px; height: 26px; border: 1px solid var(--line); border-radius: 7px; padding: 0 8px; background: var(--code-bg); color: var(--text); font: 12px var(--font); }
|
|
710
|
+
.pw-pick .rv-btn { white-space: nowrap; }
|
|
711
|
+
.pw-pick-no { color: var(--text-2); font-size: 12px; padding: 0 4px; }
|
|
712
|
+
/* collapsed: a pill with the file's title */
|
|
713
|
+
.pw-pill { display: none; }
|
|
714
|
+
.pw-win.collapsed { border-radius: 999px; }
|
|
715
|
+
.pw-win.collapsed > .pw-box { display: none; }
|
|
716
|
+
.pw-win.collapsed > .pw-pill { display: flex; align-items: center; gap: 2px; min-width: 0; padding-right: 4px; }
|
|
717
|
+
.pw-pill-open { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 6px 6px 6px 12px; border: 0; border-radius: 999px; background: transparent; color: var(--text); font: 600 12.5px var(--font); text-align: left; cursor: pointer; }
|
|
718
|
+
.pw-pill-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
719
|
+
|
|
720
|
+
/* the library (web/src/library.ts), under the bar's Library */
|
|
721
|
+
.library-wrap { position: relative; }
|
|
722
|
+
#library-pop {
|
|
723
|
+
position: absolute; top: 38px; right: 0; width: min(480px, calc(100vw - 24px)); max-height: calc(100vh - 70px); overflow: auto;
|
|
724
|
+
padding: 10px 12px 12px; border-radius: 14px; z-index: 40; display: flex; flex-direction: column; gap: 8px;
|
|
725
|
+
background: color-mix(in srgb, var(--surface-solid) 96%, transparent); box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
726
|
+
}
|
|
727
|
+
#library-pop.lb-drop { box-shadow: 0 0 0 2px var(--accent), var(--shadow-lg); }
|
|
728
|
+
#bar:has(#library-pop:not([hidden])) { z-index: 36; }
|
|
729
|
+
/* the head: its title wraps in the room left, Cancel and ✕ stay on its first line, at the right */
|
|
730
|
+
.lb-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
731
|
+
.lb-head-t { flex: 1 1 auto; min-width: 0; line-height: 1.4; overflow-wrap: anywhere; }
|
|
732
|
+
.lb-head-t .muted { font-size: 12px; }
|
|
733
|
+
.lb-head > .link, .lb-head > .icon { flex: none; line-height: 1.4; white-space: nowrap; }
|
|
734
|
+
.lb-head .icon { border: 0; background: transparent; color: var(--text-2); cursor: pointer; padding: 0 2px; }
|
|
735
|
+
.lb-hint { font-size: 12px; margin-top: -4px; }
|
|
736
|
+
.lb-add { display: flex; align-items: center; gap: 10px; }
|
|
737
|
+
.lb-upload { cursor: pointer; }
|
|
738
|
+
.lb-dropnote { font-size: 12px; }
|
|
739
|
+
.lb-url { display: flex; gap: 6px; }
|
|
740
|
+
.lb-url input, .lb-rename input { flex: 1; min-width: 0; height: 28px; border: 1px solid var(--line); border-radius: 8px; padding: 0 9px; background: var(--code-bg); color: var(--text); font: 12.5px var(--font); }
|
|
741
|
+
.lb-busy { font-size: 12px; color: var(--accent); }
|
|
742
|
+
.lb-list { display: flex; flex-direction: column; gap: 2px; }
|
|
743
|
+
.lb-row { display: grid; grid-template-columns: 1fr auto; gap: 1px 8px; padding: 7px 8px; border-radius: 9px; }
|
|
744
|
+
.lb-row:hover { background: var(--code-bg); }
|
|
745
|
+
.lb-row.archived { opacity: 0.75; }
|
|
746
|
+
.lb-title { grid-column: 1; text-align: left; border: 0; background: none; padding: 0; font: 600 13px var(--font); color: var(--text); cursor: pointer; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
747
|
+
.lb-title:hover { color: var(--accent); }
|
|
748
|
+
.lb-meta { grid-column: 1; font-size: 11.5px; color: var(--text-2); }
|
|
749
|
+
.lb-meta a { color: var(--text-2); }
|
|
750
|
+
.lb-acts { grid-column: 2; grid-row: 1 / span 2; display: flex; gap: 10px; align-items: center; }
|
|
751
|
+
.lb-missing { grid-column: 1; font-size: 11.5px; color: var(--banner-warn); }
|
|
752
|
+
.lb-rename { grid-column: 1; display: flex; gap: 6px; }
|
|
753
|
+
.lb-none, .lb-note { font-size: 12.5px; padding: 6px 2px; }
|
|
754
|
+
.lb-arch-t { align-self: flex-start; }
|
|
755
|
+
.lb-used { font-size: 11.5px; border-top: 1px solid var(--line); padding-top: 6px; }
|
|
756
|
+
|
|
757
|
+
/* a panel's papers (web/src/paperlinks.ts): each link a row that opens the paper there */
|
|
758
|
+
.pl-sec .sec { display: flex; align-items: baseline; gap: 6px; }
|
|
759
|
+
.pl-sec .pl-add { margin-left: auto; }
|
|
760
|
+
.pl-list { display: flex; flex-direction: column; gap: 1px; margin-bottom: 4px; }
|
|
761
|
+
.pl-row { display: flex; align-items: center; gap: 6px; padding: 3px 4px; border-radius: 7px; flex-wrap: wrap; }
|
|
762
|
+
.pl-row:hover { background: var(--code-bg); }
|
|
763
|
+
.pl-open { flex: 1 1 auto; min-width: 0; text-align: left; border: 0; background: none; padding: 0; color: var(--text); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
764
|
+
.pl-open:hover .pl-label { color: var(--accent); }
|
|
765
|
+
.pl-label { font-weight: 500; }
|
|
766
|
+
.pl-file { font-size: 11.5px; }
|
|
767
|
+
.pl-by { font-size: 11px; white-space: nowrap; }
|
|
768
|
+
.pl-acts { display: none; gap: 0; }
|
|
769
|
+
.pl-row:hover .pl-acts { display: inline-flex; }
|
|
770
|
+
.pl-acts .icon { border: 0; background: transparent; color: var(--text-2); width: 20px; height: 20px; border-radius: 5px; font-size: 12px; cursor: pointer; padding: 0; }
|
|
771
|
+
.pl-acts .icon:hover { background: var(--code-bg); color: var(--text); }
|
|
772
|
+
.pl-sure { flex-basis: 100%; font-size: 12px; color: var(--text-2); }
|
|
773
|
+
.pl-edit input { flex: 1; min-width: 0; height: 26px; border: 1px solid var(--line); border-radius: 7px; padding: 0 8px; background: var(--code-bg); color: var(--text); font: 12.5px var(--font); }
|
|
774
|
+
|
|
775
|
+
/* who is reviewing, and the window that asks */
|
|
776
|
+
.who {
|
|
777
|
+
border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 12.5px var(--font);
|
|
778
|
+
padding: 5px 10px; border-radius: 9px; cursor: pointer; white-space: nowrap; max-width: 180px;
|
|
779
|
+
overflow: hidden; text-overflow: ellipsis;
|
|
780
|
+
}
|
|
781
|
+
.who::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--me, var(--rv-approved)); margin-right: 6px; vertical-align: 1px; }
|
|
782
|
+
.who.unset { color: var(--text-2); }
|
|
783
|
+
.who.unset::before { background: var(--text-3); }
|
|
784
|
+
.who:hover, .who.on { border-color: var(--accent); }
|
|
785
|
+
/* a private reader (CollabSpec decision 8): their dot hollow, and an eye struck through */
|
|
786
|
+
.who.private::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--me, var(--text-3)); }
|
|
787
|
+
.who-hidden { margin-left: 6px; vertical-align: -2px; color: var(--text-2); }
|
|
788
|
+
/* the menu under the name (web/src/whomenu.ts) */
|
|
789
|
+
.who-wrap { position: relative; display: flex; min-width: 0; }
|
|
790
|
+
.who-wrap:has(> #who[hidden]) { display: none; }
|
|
791
|
+
#who-menu {
|
|
792
|
+
position: absolute; top: 38px; right: 0; width: min(320px, calc(100vw - 24px)); padding: 6px; border-radius: 14px; z-index: 40;
|
|
793
|
+
display: flex; flex-direction: column; background: color-mix(in srgb, var(--surface-solid) 96%, transparent);
|
|
794
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
795
|
+
}
|
|
796
|
+
#who-menu[hidden] { display: none; }
|
|
797
|
+
.wm-item {
|
|
798
|
+
display: flex; flex-direction: column; gap: 2px; width: 100%; padding: 7px 10px; border: 0; border-radius: 9px;
|
|
799
|
+
background: transparent; color: var(--text); font: 13px var(--font); text-align: left; cursor: pointer;
|
|
800
|
+
}
|
|
801
|
+
.wm-item:hover, .wm-item:focus-visible { background: var(--code-bg); outline: none; }
|
|
802
|
+
.wm-t { font-weight: 500; }
|
|
803
|
+
.wm-d { font-size: 11.5px; line-height: 1.35; color: var(--text-2); }
|
|
804
|
+
.wm-radio { position: relative; padding-left: 32px; }
|
|
805
|
+
.wm-radio::before {
|
|
806
|
+
content: ""; position: absolute; left: 11px; top: 9px; width: 12px; height: 12px; border-radius: 50%;
|
|
807
|
+
box-shadow: inset 0 0 0 1.5px var(--text-3);
|
|
808
|
+
}
|
|
809
|
+
.wm-radio[aria-checked="true"]::before { box-shadow: inset 0 0 0 1.5px var(--accent), inset 0 0 0 4px var(--surface-solid); background: var(--accent); }
|
|
810
|
+
.wm-sep { height: 1px; margin: 4px 6px; background: var(--line); }
|
|
811
|
+
.wm-h { margin: 4px 10px 2px; font-size: 11px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
812
|
+
.wm-note { padding: 7px 10px; font-size: 12px; color: var(--text-2); }
|
|
813
|
+
#modal {
|
|
814
|
+
position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center;
|
|
815
|
+
background: rgba(0, 0, 0, 0.22);
|
|
816
|
+
}
|
|
817
|
+
.modal-box { width: min(380px, calc(100vw - 32px)); padding: 18px 18px 14px; border-radius: 14px; display: flex; flex-direction: column; gap: 10px; }
|
|
818
|
+
.modal-title { font-weight: 600; font-size: 15px; }
|
|
819
|
+
.modal-text { color: var(--text-2); font-size: 12.5px; line-height: 1.45; }
|
|
820
|
+
/* Export (web/src/exportmodal.ts): which view, what its document holds, its title and author line,
|
|
821
|
+
the common settings, then the job */
|
|
822
|
+
#export-modal {
|
|
823
|
+
position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center;
|
|
824
|
+
background: rgba(0, 0, 0, 0.22);
|
|
825
|
+
}
|
|
826
|
+
.ex-box { width: min(580px, calc(100vw - 32px)); max-height: 90vh; overflow: auto; outline: none; }
|
|
827
|
+
.ex-head { display: flex; align-items: center; justify-content: space-between; }
|
|
828
|
+
.ex-sec { display: flex; flex-direction: column; gap: 6px; }
|
|
829
|
+
.ex-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px 10px; }
|
|
830
|
+
.ex-field { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--text-2); }
|
|
831
|
+
.ex-field.ex-wide { grid-column: span 2; }
|
|
832
|
+
.ex-field input, .ex-field select {
|
|
833
|
+
font: 12.5px var(--font); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line);
|
|
834
|
+
border-radius: 7px; padding: 5px 7px; min-width: 0;
|
|
835
|
+
}
|
|
836
|
+
.ex-checks { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 12.5px; }
|
|
837
|
+
.ex-check { cursor: pointer; white-space: nowrap; }
|
|
838
|
+
.ex-sum { font-size: 12.5px; line-height: 1.45; }
|
|
839
|
+
/* the title and the author line as they print, each with how it changes: the view's, not settings */
|
|
840
|
+
.ex-meta { gap: 8px; padding: 8px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
|
|
841
|
+
.ex-row { display: grid; grid-template-columns: 58px minmax(0, 1fr); gap: 10px; align-items: baseline; }
|
|
842
|
+
.ex-label { font-size: 11.5px; color: var(--text-2); }
|
|
843
|
+
.ex-value { font-size: 13px; line-height: 1.4; overflow-wrap: anywhere; }
|
|
844
|
+
.ex-value.ex-title { font-weight: 600; }
|
|
845
|
+
.ex-hint { margin-top: 2px; font-size: 11.5px; line-height: 1.4; color: var(--text-3); }
|
|
846
|
+
.ex-warn { font-size: 12px; }
|
|
847
|
+
.ex-prog { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text-2); }
|
|
848
|
+
.ex-bar { position: relative; flex: 0 0 120px; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
|
|
849
|
+
.ex-bar i { position: absolute; inset: 0 auto 0 0; width: 40%; border-radius: 2px; background: var(--accent); animation: ex-slide 1.1s ease-in-out infinite; }
|
|
850
|
+
@keyframes ex-slide { from { left: -40%; } to { left: 100%; } }
|
|
851
|
+
.ex-done { font-size: 12.5px; display: flex; flex-direction: column; gap: 8px; }
|
|
852
|
+
.ex-dl { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
853
|
+
.ex-dl a.rv-btn { text-decoration: none; }
|
|
854
|
+
.ex-log pre { max-height: 160px; overflow: auto; font: 11px var(--mono); white-space: pre-wrap; }
|
|
855
|
+
.ex-notes ul { margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-2); }
|
|
856
|
+
@media (max-width: 520px) { .ex-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
|
857
|
+
#who-input {
|
|
858
|
+
font: 14px var(--font); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line);
|
|
859
|
+
border-radius: 8px; padding: 8px 10px;
|
|
860
|
+
}
|
|
861
|
+
#who-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
862
|
+
.modal-err { color: var(--banner-bad); font-size: 12.5px; line-height: 1.4; }
|
|
863
|
+
.avatar {
|
|
864
|
+
display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; color: #fff;
|
|
865
|
+
font: 600 11.5px var(--font); flex: none;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* the others on this server (CollabSpec "What the page shows") */
|
|
869
|
+
.peers { display: flex; align-items: center; }
|
|
870
|
+
.peer {
|
|
871
|
+
display: inline-grid; place-items: center; width: 28px; height: 28px; margin-left: -6px; padding: 0;
|
|
872
|
+
border-radius: 50%; border: 2px solid var(--surface-solid); background: var(--c); color: #fff;
|
|
873
|
+
font: 600 10.5px var(--font); cursor: pointer; transition: transform 0.12s, opacity 0.2s;
|
|
874
|
+
}
|
|
875
|
+
.peer:first-child { margin-left: 0; }
|
|
876
|
+
.peer:hover { transform: translateY(-1px); z-index: 1; }
|
|
877
|
+
.peer.idle { opacity: 0.45; }
|
|
878
|
+
.peer.on { box-shadow: 0 0 0 2px var(--c); }
|
|
879
|
+
.peer.more { background: var(--code-bg); color: var(--text-2); cursor: default; }
|
|
880
|
+
/* the private readers, counted (CollabSpec decision 8): no one to follow, so no badge */
|
|
881
|
+
.peer-private {
|
|
882
|
+
display: inline-flex; align-items: center; height: 22px; margin-left: 6px; padding: 0 8px; border-radius: 11px;
|
|
883
|
+
border: 1px dashed var(--text-3); color: var(--text-2); font: 600 11px var(--font); white-space: nowrap; cursor: default;
|
|
884
|
+
}
|
|
885
|
+
/* someone invited by a personal link (CollabSpec decision 9): a ✓ after the name wherever it shows,
|
|
886
|
+
and on the corner of their initials among the others */
|
|
887
|
+
.vf { margin-left: 3px; color: var(--verified); font-weight: 700; font-size: 0.9em; cursor: help; }
|
|
888
|
+
.peer.verified { position: relative; }
|
|
889
|
+
.peer-vf {
|
|
890
|
+
position: absolute; right: -5px; bottom: -5px; display: grid; place-items: center; width: 15px; height: 15px;
|
|
891
|
+
border-radius: 50%; background: var(--surface-solid); color: var(--verified); box-shadow: 0 0 0 1px var(--line);
|
|
892
|
+
font: 700 9.5px/1 var(--font);
|
|
893
|
+
}
|
|
894
|
+
/* an agent among the others: a rounded square with a robot on its corner (AgentSpec decision 1) */
|
|
895
|
+
.peer.agent { position: relative; border-radius: 8px; }
|
|
896
|
+
.peer-bot {
|
|
897
|
+
position: absolute; right: -5px; bottom: -5px; display: grid; place-items: center; width: 15px; height: 15px;
|
|
898
|
+
border-radius: 50%; background: var(--surface-solid); color: var(--c); box-shadow: 0 0 0 1px var(--line);
|
|
899
|
+
}
|
|
900
|
+
.peer-bot .bot { width: 11px; height: 11px; }
|
|
901
|
+
.avatar.agent { border-radius: 6px; }
|
|
902
|
+
.bot { display: inline-block; width: 13px; height: 13px; flex: none; vertical-align: -2px; }
|
|
903
|
+
#following .bot { color: var(--c); }
|
|
904
|
+
/* a person's menu, opened from their initials, and what a request to follow came to, under them
|
|
905
|
+
(CollabSpec decision 10; web/src/peermenu.ts, web/src/askfollow.ts) */
|
|
906
|
+
.peers-wrap { position: relative; display: flex; align-items: center; }
|
|
907
|
+
#peer-menu {
|
|
908
|
+
position: absolute; top: 38px; right: 0; width: min(300px, calc(100vw - 24px)); padding: 6px; border-radius: 14px; z-index: 40;
|
|
909
|
+
display: flex; flex-direction: column; background: color-mix(in srgb, var(--surface-solid) 96%, transparent);
|
|
910
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
911
|
+
}
|
|
912
|
+
#peer-menu[hidden] { display: none; }
|
|
913
|
+
#bar:has(#peer-menu:not([hidden])) { z-index: 36; }
|
|
914
|
+
.pm-who { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 8px; align-items: center; padding: 6px 10px 4px; }
|
|
915
|
+
.pm-dot { width: 9px; height: 9px; border-radius: 50%; }
|
|
916
|
+
.pm-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
917
|
+
.pm-where { grid-column: 2; font-size: 11.5px; line-height: 1.35; color: var(--text-2); }
|
|
918
|
+
/* an item that cannot be chosen now says why in its line */
|
|
919
|
+
.wm-item[aria-disabled="true"] { cursor: default; }
|
|
920
|
+
.wm-item[aria-disabled="true"] .wm-t { color: var(--text-3); }
|
|
921
|
+
.ask-line {
|
|
922
|
+
position: absolute; top: 40px; right: 0; z-index: 21; padding: 4px 10px; border-radius: 9px; white-space: nowrap;
|
|
923
|
+
font-size: 12px; color: var(--text); background: color-mix(in srgb, var(--surface-solid) 96%, transparent);
|
|
924
|
+
}
|
|
925
|
+
/* each person's part in your request to follow, on the corner of their initials the next ones do not
|
|
926
|
+
cover: following, declined, no answer, or still to answer */
|
|
927
|
+
.peer.asked { position: relative; }
|
|
928
|
+
.peer-ask {
|
|
929
|
+
position: absolute; left: -5px; top: -5px; display: grid; place-items: center; width: 15px; height: 15px;
|
|
930
|
+
border-radius: 50%; color: #fff; box-shadow: 0 0 0 1.5px var(--surface-solid); font: 700 9px/1 var(--font);
|
|
931
|
+
}
|
|
932
|
+
.peer-ask.ask-follow { background: var(--st-ok); }
|
|
933
|
+
.peer-ask.ask-decline { background: var(--bad); }
|
|
934
|
+
.peer-ask.ask-timeout { background: var(--text-3); }
|
|
935
|
+
.peer-ask.ask-waiting { background: var(--accent); animation: pulse 1.6s ease-in-out infinite; }
|
|
936
|
+
/* someone asks you to follow: at the top centre, in the asker's colour, over everything but a window
|
|
937
|
+
that asks you something; its countdown a ring and a bar running down */
|
|
938
|
+
#ask-banner {
|
|
939
|
+
position: fixed; top: 108px; left: 50%; transform: translateX(-50%); z-index: 41;
|
|
940
|
+
display: flex; align-items: center; gap: 12px; max-width: calc(100vw - 24px); padding: 10px 12px 12px;
|
|
941
|
+
border-radius: 14px; overflow: hidden; font-size: 13.5px; color: var(--text);
|
|
942
|
+
background: color-mix(in srgb, var(--surface-solid) 97%, transparent);
|
|
943
|
+
box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--c) 55%, transparent), var(--shadow-lg);
|
|
944
|
+
animation: ab-in 0.22s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
945
|
+
}
|
|
946
|
+
@keyframes ab-in { from { opacity: 0; transform: translate(-50%, -8px); } }
|
|
947
|
+
.ab-mark { display: grid; place-items: center; flex: none; width: 32px; height: 32px; border-radius: 50%; background: var(--c); color: #fff; font: 600 12px var(--font); }
|
|
948
|
+
.ab-mark.agent { border-radius: 9px; }
|
|
949
|
+
.ab-mark .bot { width: 18px; height: 18px; vertical-align: 0; }
|
|
950
|
+
.ab-text { display: flex; flex-direction: column; min-width: 0; }
|
|
951
|
+
.ab-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
952
|
+
.ab-who b { font-weight: 650; }
|
|
953
|
+
.ab-sub { font-size: 11.5px; color: var(--text-2); }
|
|
954
|
+
.ab-count { position: relative; display: grid; place-items: center; flex: none; width: 26px; height: 26px; }
|
|
955
|
+
.ab-count svg { position: absolute; inset: 0; transform: rotate(-90deg); }
|
|
956
|
+
.ab-track { fill: none; stroke: var(--line); stroke-width: 2.5; }
|
|
957
|
+
.ab-left { fill: none; stroke: var(--c); stroke-width: 2.5; stroke-linecap: round; stroke-dashoffset: var(--ring, 0px); transition: stroke-dashoffset 0.25s linear; }
|
|
958
|
+
.ab-secs { font: 600 10.5px var(--font); font-variant-numeric: tabular-nums; color: var(--text-2); }
|
|
959
|
+
#ask-banner .rv-btn { flex: none; padding: 5px 12px; font-size: 12.5px; }
|
|
960
|
+
.ab-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--line); }
|
|
961
|
+
.ab-bar i { display: block; height: 100%; background: var(--c); transform-origin: left; transform: scaleX(var(--left, 1)); transition: transform 0.25s linear; }
|
|
962
|
+
/* following someone: low in the middle, where the tabs and the strips above stay readable; in the
|
|
963
|
+
windows' layer, above the source windows while it is the strip alone; a conversation's window
|
|
964
|
+
takes its place among them (web/src/floatwin.ts) */
|
|
965
|
+
#following {
|
|
966
|
+
position: fixed; bottom: 52px; left: 50%; transform: translateX(-50%); z-index: 36;
|
|
967
|
+
display: flex; flex-direction: column; gap: 8px; padding: 5px 6px 5px 12px; border-radius: 10px;
|
|
968
|
+
font-size: 12.5px; color: var(--text);
|
|
969
|
+
}
|
|
970
|
+
.fl-strip { display: flex; align-items: center; gap: 6px; white-space: nowrap; min-width: 0; }
|
|
971
|
+
.fl-who { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
972
|
+
#following .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c); flex: none; }
|
|
973
|
+
.fl-strip button, .fl-pill > button[data-unfollow] {
|
|
974
|
+
display: inline-grid; place-items: center; flex: none; padding: 0; border: 0; background: transparent;
|
|
975
|
+
color: var(--text-2); cursor: pointer; width: 22px; height: 22px; border-radius: 6px;
|
|
976
|
+
}
|
|
977
|
+
.fl-strip button:hover, .fl-pill > button[data-unfollow]:hover { background: var(--code-bg); color: var(--text); }
|
|
978
|
+
/* the strip alone has no state, no new conversation, no pin, no collapsing, no pill, no edges:
|
|
979
|
+
those are the window's */
|
|
980
|
+
.fl-st, .fl-strip [data-restart], .fl-strip [data-pin], .fl-strip [data-collapse], .fl-pill, .fl-rz { display: none; }
|
|
981
|
+
.peer.offline { filter: grayscale(1); opacity: 0.45; }
|
|
982
|
+
/* an agent's state (AgentSpec decision 8): a dot on its badge, and its line in the conversation */
|
|
983
|
+
.st-listening { --state: var(--st-ok); }
|
|
984
|
+
.st-thinking { --state: var(--st-sorry); }
|
|
985
|
+
.st-working { --state: var(--st-building); }
|
|
986
|
+
.st-offline { --state: var(--text-3); }
|
|
987
|
+
.peer-dot {
|
|
988
|
+
position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%;
|
|
989
|
+
background: var(--state); box-shadow: 0 0 0 2px var(--surface-solid);
|
|
990
|
+
}
|
|
991
|
+
.st-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--state); flex: none; }
|
|
992
|
+
.peer-dot.st-thinking, .tk-state.st-thinking .st-dot, .st-dot.st-thinking { animation: pulse 1.6s ease-in-out infinite; }
|
|
993
|
+
@media (prefers-reduced-motion: reduce) { .peer-dot.st-thinking, .tk-state.st-thinking .st-dot, .st-dot.st-thinking { animation: none; } }
|
|
994
|
+
/* talking with an agent while following it (web/src/talk.ts): a window (web/src/chatwin.ts, which
|
|
995
|
+
sets its place and size) — the strip its title bar, dragged to move it, then the thread, filling
|
|
996
|
+
it, and at its foot the state line and the box; every edge and corner resizes it */
|
|
997
|
+
#following.talking {
|
|
998
|
+
transform: none; gap: 0; padding: 0; border-radius: 14px; box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
999
|
+
}
|
|
1000
|
+
#following.talking > .fl-strip {
|
|
1001
|
+
flex: none; padding: 6px 6px 6px 12px; border-bottom: 1px solid var(--line); cursor: grab;
|
|
1002
|
+
user-select: none; -webkit-user-select: none; touch-action: none;
|
|
1003
|
+
}
|
|
1004
|
+
#following.talking.moving > .fl-strip { cursor: grabbing; }
|
|
1005
|
+
#following.talking .fl-who { flex: 1; }
|
|
1006
|
+
#following.talking .fl-strip > .dot { display: none; }
|
|
1007
|
+
#following.talking .fl-st, #following.talking .fl-strip [data-restart], #following.talking .fl-strip [data-pin], #following.talking .fl-strip [data-collapse] { display: inline-grid; }
|
|
1008
|
+
/* pinned (web/src/talkpins.ts): the pin filled in the accent, as a pinned source window's */
|
|
1009
|
+
.fl-strip [data-pin][aria-pressed="true"] { color: var(--accent); }
|
|
1010
|
+
.fl-strip [data-pin][aria-pressed="true"] path { fill: color-mix(in srgb, var(--accent) 35%, transparent); }
|
|
1011
|
+
/* nothing said since the conversation began: the button stays, with its tooltip, and does nothing */
|
|
1012
|
+
.fl-strip [data-restart][aria-disabled="true"] { opacity: 0.4; cursor: default; background: transparent; color: var(--text-2); }
|
|
1013
|
+
#following.talking > .fl-rz { display: block; position: absolute; z-index: 2; touch-action: none; }
|
|
1014
|
+
.fl-rz-n, .fl-rz-s { left: 12px; right: 12px; height: 8px; cursor: ns-resize; }
|
|
1015
|
+
.fl-rz-e, .fl-rz-w { top: 12px; bottom: 12px; width: 8px; cursor: ew-resize; }
|
|
1016
|
+
.fl-rz-n { top: -4px; }
|
|
1017
|
+
.fl-rz-s { bottom: -4px; }
|
|
1018
|
+
.fl-rz-e { right: -4px; }
|
|
1019
|
+
.fl-rz-w { left: -4px; }
|
|
1020
|
+
.fl-rz-ne, .fl-rz-nw, .fl-rz-se, .fl-rz-sw { width: 16px; height: 16px; }
|
|
1021
|
+
.fl-rz-ne { top: -5px; right: -5px; cursor: nesw-resize; }
|
|
1022
|
+
.fl-rz-sw { bottom: -5px; left: -5px; cursor: nesw-resize; }
|
|
1023
|
+
.fl-rz-nw { top: -5px; left: -5px; cursor: nwse-resize; }
|
|
1024
|
+
.fl-rz-se { bottom: -5px; right: -5px; cursor: nwse-resize; }
|
|
1025
|
+
/* a finger needs more room than a pointer */
|
|
1026
|
+
@media (pointer: coarse) {
|
|
1027
|
+
.fl-rz-n, .fl-rz-s { height: 18px; }
|
|
1028
|
+
.fl-rz-n { top: -9px; }
|
|
1029
|
+
.fl-rz-s { bottom: -9px; }
|
|
1030
|
+
.fl-rz-e, .fl-rz-w { width: 18px; }
|
|
1031
|
+
.fl-rz-e { right: -9px; }
|
|
1032
|
+
.fl-rz-w { left: -9px; }
|
|
1033
|
+
.fl-rz-ne, .fl-rz-nw, .fl-rz-se, .fl-rz-sw { width: 26px; height: 26px; }
|
|
1034
|
+
}
|
|
1035
|
+
#following.moving, #following.sizing { user-select: none; -webkit-user-select: none; }
|
|
1036
|
+
#following.talking > #talk { flex: 1 1 auto; min-height: 0; padding: 8px 10px 10px 12px; }
|
|
1037
|
+
/* collapsed: a pill of one line, the agent's state and the start of its last message; a click
|
|
1038
|
+
opens the window again; a reply meanwhile lights it a moment, and marks it until then */
|
|
1039
|
+
#following.talking.collapsed { border-radius: 999px; }
|
|
1040
|
+
#following.talking.collapsed > .fl-strip, #following.talking.collapsed > #talk, #following.talking.collapsed > .fl-rz { display: none; }
|
|
1041
|
+
#following.talking.collapsed > .fl-pill { display: flex; align-items: center; gap: 2px; min-width: 0; padding-right: 6px; }
|
|
1042
|
+
.fl-pill-open {
|
|
1043
|
+
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; padding: 7px 6px 7px 12px; border: 0;
|
|
1044
|
+
border-radius: 999px; background: transparent; color: var(--text); font: 12.5px var(--font); text-align: left; cursor: pointer;
|
|
1045
|
+
}
|
|
1046
|
+
.fl-pill-text { display: flex; align-items: center; gap: 6px; min-width: 0; white-space: nowrap; }
|
|
1047
|
+
.fl-pill-text .bot { color: var(--c); }
|
|
1048
|
+
.fl-pill-state { color: var(--text-2); flex: none; }
|
|
1049
|
+
.fl-pill-msg { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--text-2); }
|
|
1050
|
+
.fl-pill-msg::before { content: "— "; color: var(--text-3); }
|
|
1051
|
+
.fl-new { display: none; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
|
|
1052
|
+
#following.unseen .fl-new { display: inline-block; }
|
|
1053
|
+
#following.unseen .fl-pill-msg { color: var(--text); }
|
|
1054
|
+
#following.flash { animation: fl-flash 1.6s ease-out; }
|
|
1055
|
+
@keyframes fl-flash {
|
|
1056
|
+
0%, 35% { box-shadow: 0 0 0 1px var(--line), 0 0 0 5px color-mix(in srgb, var(--c) 45%, transparent), var(--shadow-lg); background: color-mix(in srgb, var(--c) 14%, var(--surface-solid)); }
|
|
1057
|
+
100% { box-shadow: 0 0 0 1px var(--line), 0 0 0 0 transparent, var(--shadow-lg); }
|
|
1058
|
+
}
|
|
1059
|
+
@media (prefers-reduced-motion: reduce) { #following.flash { animation: none; } }
|
|
1060
|
+
#talk { display: flex; flex-direction: column; gap: 8px; }
|
|
1061
|
+
#talk[hidden] { display: none; }
|
|
1062
|
+
/* the thread fills the window and scrolls, its messages from its foot up, as a conversation reads;
|
|
1063
|
+
at its end it stays there however the window is resized (talk.ts), which the browser's own scroll
|
|
1064
|
+
anchoring would undo, keeping a message above in place */
|
|
1065
|
+
.tk-thread {
|
|
1066
|
+
flex: 1 1 auto; min-height: 0; overflow: auto; overflow-anchor: none; display: flex; flex-direction: column; gap: 9px; padding-right: 4px;
|
|
1067
|
+
}
|
|
1068
|
+
.tk-thread > :first-child { margin-top: auto; }
|
|
1069
|
+
.tk-state, .tk-form { flex: none; }
|
|
1070
|
+
.tk-msg { font-size: 12.5px; line-height: 1.45; padding-left: 9px; border-left: 2px solid var(--line); }
|
|
1071
|
+
.tk-msg.agent { border-left-color: var(--c); }
|
|
1072
|
+
.tk-head { display: flex; align-items: center; gap: 4px; font-size: 11.5px; margin-bottom: 1px; }
|
|
1073
|
+
.tk-head .bot { color: var(--c); }
|
|
1074
|
+
.tk-text { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
1075
|
+
.tk-text code { font: 11.5px var(--mono); background: var(--code-bg); padding: 0 3px; border-radius: 4px; }
|
|
1076
|
+
.tk-pre { margin: 4px 0; padding: 6px 8px; background: var(--code-bg); border-radius: 6px; overflow: auto; font: 11.5px var(--mono); white-space: pre; }
|
|
1077
|
+
.tk-pre code { background: none; padding: 0; }
|
|
1078
|
+
.tk-decl { color: var(--accent); text-decoration: none; }
|
|
1079
|
+
.tk-decl:hover { text-decoration: underline; }
|
|
1080
|
+
.tk-empty { font-size: 12px; line-height: 1.45; }
|
|
1081
|
+
.tk-state { display: flex; align-items: center; gap: 6px; font-size: 11.5px; line-height: 1.4; color: var(--text-2); min-width: 0; }
|
|
1082
|
+
.tk-state[hidden] { display: none; }
|
|
1083
|
+
.tk-state > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1084
|
+
.tk-state code { font: 11px var(--mono); background: var(--code-bg); padding: 0 3px; border-radius: 4px; }
|
|
1085
|
+
.tk-wait { color: var(--text-3); font-style: italic; }
|
|
1086
|
+
/* a new conversation (the owner's decision of 2026-10-11): a rule across the thread with who
|
|
1087
|
+
started it and when; what came before it, one line that opens it */
|
|
1088
|
+
.tk-divider { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--text-2); }
|
|
1089
|
+
.tk-divider::before, .tk-divider::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
|
|
1090
|
+
.tk-divider > span { flex: none; max-width: 85%; text-align: center; }
|
|
1091
|
+
.tk-fold {
|
|
1092
|
+
align-self: center; display: inline-flex; align-items: center; gap: 5px; padding: 2px 10px; border: 0; border-radius: 999px;
|
|
1093
|
+
background: var(--code-bg); color: var(--text-2); font: 11.5px var(--font); cursor: pointer;
|
|
1094
|
+
}
|
|
1095
|
+
.tk-fold:hover { color: var(--text); }
|
|
1096
|
+
.tk-chev { width: 0; height: 0; border-left: 4px solid currentColor; border-top: 3.5px solid transparent; border-bottom: 3.5px solid transparent; transition: transform 0.15s; }
|
|
1097
|
+
.tk-fold[aria-expanded="true"] .tk-chev { transform: rotate(90deg); }
|
|
1098
|
+
@media (prefers-reduced-motion: reduce) { .tk-chev { transition: none; } }
|
|
1099
|
+
.tk-form { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; }
|
|
1100
|
+
.tk-form textarea {
|
|
1101
|
+
flex: 1; min-width: 0; resize: none; font: 12.5px var(--font); color: var(--text); background: var(--surface-solid);
|
|
1102
|
+
border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
|
|
1103
|
+
}
|
|
1104
|
+
.tk-form textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
1105
|
+
.tk-form textarea:disabled, .tk-form button:disabled { opacity: 0.6; }
|
|
1106
|
+
.tk-form button:disabled { cursor: default; filter: none; }
|
|
1107
|
+
.tk-err { flex-basis: 100%; color: var(--banner-bad); font-size: 12px; }
|
|
1108
|
+
body.following::after {
|
|
1109
|
+
content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 30;
|
|
1110
|
+
box-shadow: inset 0 0 0 3px var(--follow);
|
|
1111
|
+
}
|
|
1112
|
+
/* the timeline (CollabSpec "Activity") */
|
|
1113
|
+
.act-btn {
|
|
1114
|
+
display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border-radius: 9px;
|
|
1115
|
+
border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 12.5px var(--font); cursor: pointer;
|
|
1116
|
+
}
|
|
1117
|
+
.act-btn svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1118
|
+
.act-btn:hover, .act-btn.on { border-color: var(--accent); }
|
|
1119
|
+
/* Activity is an icon, its count of what is new on its corner */
|
|
1120
|
+
.act-icon { position: relative; width: 32px; padding: 0; justify-content: center; }
|
|
1121
|
+
.act-icon .act-badge { position: absolute; top: -6px; right: -7px; box-shadow: 0 0 0 2px var(--surface-solid); }
|
|
1122
|
+
/* sharing: a link to this view for a person, a prompt with a token for an AI agent (web/src/share.ts) */
|
|
1123
|
+
.share-wrap { position: relative; }
|
|
1124
|
+
#share-pop {
|
|
1125
|
+
position: absolute; top: 38px; right: 0; width: min(440px, calc(100vw - 24px)); max-height: calc(100vh - 70px); overflow: auto;
|
|
1126
|
+
padding: 10px 12px 12px; border-radius: 14px; z-index: 40;
|
|
1127
|
+
display: flex; flex-direction: column; gap: 10px; background: color-mix(in srgb, var(--surface-solid) 96%, transparent);
|
|
1128
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
1129
|
+
}
|
|
1130
|
+
.sh-tabs { display: flex; gap: 2px; padding: 2px; border-radius: 9px; background: var(--code-bg); }
|
|
1131
|
+
.sh-tabs button {
|
|
1132
|
+
flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; height: 26px; border: 0; border-radius: 7px;
|
|
1133
|
+
background: transparent; color: var(--text-2); font: 12.5px var(--font); cursor: pointer;
|
|
1134
|
+
}
|
|
1135
|
+
.sh-tabs button[aria-selected="true"] { background: var(--surface-solid); color: var(--text); box-shadow: 0 0 0 1px var(--line); font-weight: 600; }
|
|
1136
|
+
.sh-body { display: flex; flex-direction: column; gap: 8px; }
|
|
1137
|
+
.sh-title { font-weight: 600; }
|
|
1138
|
+
.sh-url, .sh-prompt {
|
|
1139
|
+
width: 100%; font: 11.5px var(--mono); color: var(--text); background: var(--code-bg); border: 1px solid var(--line);
|
|
1140
|
+
border-radius: 7px; padding: 6px 8px;
|
|
1141
|
+
}
|
|
1142
|
+
.sh-prompt { height: 200px; resize: vertical; line-height: 1.45; white-space: pre-wrap; }
|
|
1143
|
+
/* Exactly what I see: whether the links carry everything followed or only the view, a switch */
|
|
1144
|
+
.sh-exact {
|
|
1145
|
+
align-self: flex-start; display: inline-flex; align-items: center; gap: 8px; margin-bottom: -4px; padding: 2px 0; border: 0;
|
|
1146
|
+
background: none; color: var(--text); font: 600 12.5px var(--font); cursor: pointer;
|
|
1147
|
+
}
|
|
1148
|
+
.sh-switch { position: relative; flex: none; width: 28px; height: 16px; border-radius: 8px; background: color-mix(in srgb, var(--text-3) 60%, transparent); transition: background 0.15s; }
|
|
1149
|
+
.sh-switch::after {
|
|
1150
|
+
content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%;
|
|
1151
|
+
background: var(--surface-solid); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); transition: transform 0.15s;
|
|
1152
|
+
}
|
|
1153
|
+
.sh-exact[aria-checked="true"] .sh-switch { background: var(--accent); }
|
|
1154
|
+
.sh-exact[aria-checked="true"] .sh-switch::after { transform: translateX(12px); }
|
|
1155
|
+
.sh-exact:focus-visible { outline: none; }
|
|
1156
|
+
.sh-exact:focus-visible .sh-switch { box-shadow: 0 0 0 2px var(--surface-solid), 0 0 0 4px var(--accent); }
|
|
1157
|
+
.sh-note { font-size: 11.5px; line-height: 1.45; }
|
|
1158
|
+
.sh-form { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 10px; align-items: center; }
|
|
1159
|
+
.sh-field { display: contents; font-size: 12.5px; }
|
|
1160
|
+
.sh-field > span { color: var(--text-2); }
|
|
1161
|
+
.sh-field input, .sh-field select {
|
|
1162
|
+
font: 12.5px var(--font); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line); border-radius: 7px; padding: 5px 7px;
|
|
1163
|
+
}
|
|
1164
|
+
.sh-tokens { display: flex; flex-direction: column; gap: 6px; padding-top: 8px; border-top: 1px solid var(--line); }
|
|
1165
|
+
.sh-sub { font-size: 11.5px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
1166
|
+
/* a token in force: a click on it shows its prompt again; the one on show is marked */
|
|
1167
|
+
.sh-tok { display: flex; align-items: center; gap: 6px; font-size: 12.5px; line-height: 1.4; margin: 0 -6px; padding: 3px 6px; border-radius: 8px; }
|
|
1168
|
+
.sh-tok.on { background: color-mix(in srgb, var(--accent) 9%, transparent); }
|
|
1169
|
+
.sh-tok-text { flex: 1; min-width: 0; cursor: pointer; }
|
|
1170
|
+
.sh-tok-text:hover b { color: var(--accent); }
|
|
1171
|
+
.sh-tok-text .muted { font-size: 11.5px; }
|
|
1172
|
+
.sh-tok .bot { margin-right: 4px; color: var(--text-2); }
|
|
1173
|
+
.sh-lvl { font-size: 11px; padding: 0 5px; border-radius: 5px; background: var(--code-bg); color: var(--text-2); }
|
|
1174
|
+
.sh-act { flex: none; }
|
|
1175
|
+
/* a personal link in force: nothing to show again, so no pointer */
|
|
1176
|
+
.sh-person .sh-tok-text { cursor: default; }
|
|
1177
|
+
.sh-person .sh-tok-text:hover b { color: inherit; }
|
|
1178
|
+
.act-badge {
|
|
1179
|
+
min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--bad); color: #fff;
|
|
1180
|
+
font: 600 10.5px/18px var(--font); text-align: center;
|
|
1181
|
+
}
|
|
1182
|
+
#activity, #lostfound {
|
|
1183
|
+
position: fixed; top: calc(108px + var(--selbar-h, 0px)); right: 12px; bottom: 56px; width: 400px; z-index: 7;
|
|
1184
|
+
border-radius: 18px; overflow: auto; padding: 16px 18px 22px;
|
|
1185
|
+
transform: translateX(calc(100% + 24px)); transition: transform 0.32s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
1186
|
+
}
|
|
1187
|
+
#activity.open, #lostfound.open { transform: none; }
|
|
1188
|
+
.act-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
|
|
1189
|
+
.act-title { font-weight: 700; font-size: 18px; letter-spacing: -0.01em; }
|
|
1190
|
+
.act-filters { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 8px; }
|
|
1191
|
+
.act-day { margin: 14px 0 4px; font-size: 11.5px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
1192
|
+
.act-item { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px; padding: 6px 0; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.45; }
|
|
1193
|
+
.act-time { color: var(--text-3); font-variant-numeric: tabular-nums; font-size: 11.5px; padding-top: 1px; white-space: nowrap; min-width: 34px; }
|
|
1194
|
+
.act-text .ok { color: var(--rv-approved); font-weight: 600; }
|
|
1195
|
+
.act-text .bad { color: var(--bad); font-weight: 600; }
|
|
1196
|
+
.act-text .commented { color: var(--rv-commented); font-weight: 600; }
|
|
1197
|
+
.act-text .warn { color: var(--banner-warn); font-weight: 600; }
|
|
1198
|
+
.act-ref { border: 0; background: transparent; padding: 0; font: inherit; color: var(--accent); cursor: pointer; }
|
|
1199
|
+
.act-ref:hover { text-decoration: underline; }
|
|
1200
|
+
.act-ref.mono, .act-text .mono { font-family: var(--mono); font-size: 11.5px; }
|
|
1201
|
+
.act-ref .star { color: var(--target-star); margin-right: 1px; }
|
|
1202
|
+
.act-gone { color: var(--text-3); }
|
|
1203
|
+
.act-quote { margin-top: 3px; padding-left: 8px; border-left: 2px solid var(--line); color: var(--text-2); white-space: pre-wrap; }
|
|
1204
|
+
.act-quote.md { white-space: normal; }
|
|
1205
|
+
.act-warn { margin-top: 3px; color: var(--banner-warn); font-size: 12px; }
|
|
1206
|
+
.act-details summary { cursor: pointer; color: var(--text-2); font-size: 12px; margin-top: 2px; }
|
|
1207
|
+
.act-list { margin-top: 2px; font-size: 12px; }
|
|
1208
|
+
.act-empty { padding: 18px 0; }
|
|
1209
|
+
/* what agents did: their mark, their notes, Undo on their layouts */
|
|
1210
|
+
.act-agent .bot { margin-right: 3px; color: var(--text-2); }
|
|
1211
|
+
.act-note { border-left-style: dashed; color: var(--text); }
|
|
1212
|
+
.act-note-go { display: block; width: 100%; border: 0; border-left: 2px dashed var(--line); background: transparent; font: inherit; text-align: left; cursor: pointer; }
|
|
1213
|
+
.act-note-go:hover { border-left-color: var(--accent); }
|
|
1214
|
+
.act-note.gone { text-decoration: line-through; color: var(--text-3); }
|
|
1215
|
+
.act-undo {
|
|
1216
|
+
margin-left: 4px; padding: 0 7px; border-radius: 6px; border: 1px solid var(--line); background: var(--surface-solid);
|
|
1217
|
+
color: var(--accent); font: 600 11.5px var(--font); line-height: 18px; cursor: pointer;
|
|
1218
|
+
}
|
|
1219
|
+
.act-undo:hover { border-color: var(--accent); }
|
|
1220
|
+
.act-undo:disabled { opacity: 0.5; cursor: default; }
|
|
1221
|
+
.act-who .bot { margin-right: 4px; }
|
|
1222
|
+
.act-key { font-family: var(--mono); font-size: 11.5px; }
|
|
1223
|
+
/* the lost-and-found (web/src/lostfound.ts): by name what is lost, then the migrations, then what
|
|
1224
|
+
is archived */
|
|
1225
|
+
.lf-intro { font-size: 12px; line-height: 1.45; margin-bottom: 10px; }
|
|
1226
|
+
.lf-sec-h { margin: 16px 0 6px; font-size: 11.5px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
1227
|
+
details.lf-archived > summary { cursor: pointer; }
|
|
1228
|
+
.lf-none { font-size: 12px; padding: 4px 0 2px; }
|
|
1229
|
+
.lf-group, .lf-mig, .lf-arch-item { padding: 8px 0; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.45; border-radius: 6px; transition: background 0.4s; }
|
|
1230
|
+
.lf-name { font: 600 12px var(--mono); overflow-wrap: anywhere; }
|
|
1231
|
+
.lf-last { font-size: 11.5px; margin-top: 1px; overflow-wrap: anywhere; }
|
|
1232
|
+
.lf-last .mono { font: 11px var(--mono); }
|
|
1233
|
+
.lf-sugg { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 6px; margin-top: 4px; font-size: 12px; }
|
|
1234
|
+
.lf-score { font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
|
|
1235
|
+
.lf-why { font-size: 11.5px; }
|
|
1236
|
+
.lf-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
|
|
1237
|
+
.lf-acts .sbtn:disabled { opacity: 0.5; cursor: default; }
|
|
1238
|
+
.lf-confirm { margin-top: 6px; padding: 8px 10px; border-radius: 8px; background: color-mix(in srgb, var(--accent) 8%, transparent); font-size: 12px; }
|
|
1239
|
+
.lf-entry { display: grid; grid-template-columns: 52px minmax(0, 1fr) max-content; gap: 2px 8px; align-items: start; margin-top: 6px; }
|
|
1240
|
+
.lf-entry > .act-warn { grid-column: 2 / -1; }
|
|
1241
|
+
.lf-kind { font-size: 10.5px; font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.03em; padding-top: 2px; }
|
|
1242
|
+
.lf-entry-t { min-width: 0; overflow-wrap: anywhere; }
|
|
1243
|
+
.lf-when { color: var(--text-3); font-size: 11.5px; white-space: nowrap; }
|
|
1244
|
+
.lf-arch {
|
|
1245
|
+
padding: 0 7px; border-radius: 6px; border: 1px solid var(--line); background: var(--surface-solid);
|
|
1246
|
+
color: var(--text-2); font: 500 11px var(--font); line-height: 18px; cursor: pointer;
|
|
1247
|
+
}
|
|
1248
|
+
.lf-arch:hover { border-color: var(--accent); color: var(--accent); }
|
|
1249
|
+
.lf-arch:disabled, .act-undo:disabled { opacity: 0.5; cursor: default; }
|
|
1250
|
+
.lf-mv { font-size: 12.5px; }
|
|
1251
|
+
.lf-how { color: var(--text-2); font-size: 12px; }
|
|
1252
|
+
.lf-carried { color: var(--text-2); font-size: 11.5px; }
|
|
1253
|
+
.lf-mig.undone .lf-mv { text-decoration: line-through; text-decoration-color: var(--text-3); }
|
|
1254
|
+
.lf-arch-item .lf-entry-t { margin-top: 2px; }
|
|
1255
|
+
.lf-flash { background: color-mix(in srgb, var(--accent) 13%, transparent); }
|
|
1256
|
+
/* an agent's advice in the review box: apart from the reviewers' opinions, dashed */
|
|
1257
|
+
.rv-advice { display: flex; flex-direction: column; gap: 4px; padding: 6px 8px; border-radius: 8px; border: 1px dashed color-mix(in srgb, var(--text-3) 70%, transparent); }
|
|
1258
|
+
.rv-adv-h { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-2); }
|
|
1259
|
+
.rv-adv { font-size: 12.5px; line-height: 1.45; }
|
|
1260
|
+
.rv-adv.old { opacity: 0.6; }
|
|
1261
|
+
.rv-adv-approve .rv-adv-v { color: color-mix(in srgb, var(--rv-approved) 80%, var(--text)); }
|
|
1262
|
+
.rv-adv-comment .rv-adv-v { color: var(--rv-advice-comment); }
|
|
1263
|
+
.rv-adv-c { margin: 2px 0 0 0; color: var(--text-2); white-space: pre-wrap; font-size: 12px; }
|
|
1264
|
+
.rv-adv-c.md { white-space: normal; }
|
|
1265
|
+
.rv-adv-c > p:first-child::before { content: "— "; }
|
|
1266
|
+
/* in a target's TCB in review order: what an agent advises, beside the status */
|
|
1267
|
+
.q-adv { display: inline-flex; margin-left: 5px; vertical-align: -1px; }
|
|
1268
|
+
.q-adv-comment { color: var(--rv-advice-comment); }
|
|
1269
|
+
.q-adv-approve { color: var(--rv-advice-approve); }
|
|
1270
|
+
.q-adv .bot { width: 11px; height: 11px; }
|
|
1271
|
+
.p-also { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 4px 0 2px; font-size: 12px; color: var(--text-2); }
|
|
1272
|
+
.p-also .avatar { width: 20px; height: 20px; font-size: 9px; }
|
|
1273
|
+
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }
|
|
1274
|
+
.rv-btn.primary { background: var(--accent); border-color: var(--accent); color: white; }
|
|
1275
|
+
.rv-btn.primary:hover { color: white; filter: brightness(1.08); }
|
|
1276
|
+
.tk-ref:hover { text-decoration: underline; background: var(--code-bg); }
|
|
1277
|
+
.brand .logo { font-size: 17px; }
|
|
1278
|
+
.project { color: var(--text-2); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1279
|
+
.snapshot {
|
|
1280
|
+
font-size: 11px; font-weight: 600; color: var(--accent); background: rgba(125, 92, 240, 0.12);
|
|
1281
|
+
padding: 2px 8px; border-radius: 999px; white-space: nowrap;
|
|
1282
|
+
}
|
|
1283
|
+
.build-pill {
|
|
1284
|
+
display: inline-flex; align-items: center; gap: 6px; border: 0; border-radius: 999px;
|
|
1285
|
+
padding: 3px 10px; font-size: 11.5px; font-weight: 600; white-space: nowrap;
|
|
1286
|
+
background: var(--code-bg); color: var(--text-2); max-width: 340px; overflow: hidden; text-overflow: ellipsis;
|
|
1287
|
+
}
|
|
1288
|
+
.build-pill .b-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--st-ok); flex: none; }
|
|
1289
|
+
.build-pill.building .b-dot { background: var(--st-building); animation: pulse 1.1s ease-in-out infinite; }
|
|
1290
|
+
.build-pill.bad { color: var(--st-failed); background: rgba(255, 59, 48, 0.1); }
|
|
1291
|
+
.build-pill.bad .b-dot { background: var(--st-failed); }
|
|
1292
|
+
.build-pill.warn .b-dot { background: var(--st-sorry); }
|
|
1293
|
+
.build-pill.stale .b-dot, .build-pill.off .b-dot { background: var(--st-stale); }
|
|
1294
|
+
@keyframes pulse { 50% { opacity: 0.3; } }
|
|
1295
|
+
#progress { position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px; opacity: 0; transition: opacity 0.3s; }
|
|
1296
|
+
#progress.on { opacity: 1; }
|
|
1297
|
+
#progress > div { height: 100%; width: 0; background: var(--grad); border-radius: 2px; transition: width 0.4s; }
|
|
1298
|
+
#build-pop {
|
|
1299
|
+
position: fixed; top: 66px; left: 12px; width: 460px; max-height: 60vh; overflow: auto; z-index: 36;
|
|
1300
|
+
border-radius: 14px; padding: 10px;
|
|
1301
|
+
}
|
|
1302
|
+
.pop-h { font-weight: 600; margin: 4px 4px 6px; }
|
|
1303
|
+
/* the build-status popover's head: when the build on show finished, its commit, the two ways into
|
|
1304
|
+
the history, the recent builds (web/src/buildpop.ts) */
|
|
1305
|
+
.bp-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin: 2px 4px 8px; font-size: 12.5px; }
|
|
1306
|
+
.bp-built { font-weight: 600; }
|
|
1307
|
+
.bp-commit { color: var(--text-2); font-size: 12px; white-space: nowrap; }
|
|
1308
|
+
.bp-commit .mono { font: 11.5px var(--mono); color: var(--text); }
|
|
1309
|
+
.bp-dirty { font-size: 10.5px; font-weight: 600; color: var(--banner-warn); background: rgba(255, 159, 10, 0.13); padding: 0 5px; border-radius: 5px; }
|
|
1310
|
+
.bp-btns { display: flex; gap: 6px; margin: 0 4px 10px; }
|
|
1311
|
+
.bp-btn {
|
|
1312
|
+
flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; padding: 0 10px;
|
|
1313
|
+
border-radius: 9px; border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 500 12.5px var(--font); cursor: pointer;
|
|
1314
|
+
}
|
|
1315
|
+
.bp-btn:hover { border-color: var(--accent); color: var(--accent); }
|
|
1316
|
+
.bp-btn svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; flex: none; }
|
|
1317
|
+
.bp-count {
|
|
1318
|
+
min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; font: 600 10.5px/18px var(--font); text-align: center;
|
|
1319
|
+
background: var(--code-bg); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--line);
|
|
1320
|
+
}
|
|
1321
|
+
.bp-count.lost { background: var(--accent); color: #fff; box-shadow: none; }
|
|
1322
|
+
.bp-build {
|
|
1323
|
+
display: flex; align-items: baseline; gap: 8px; width: 100%; border: 0; background: transparent; text-align: left;
|
|
1324
|
+
padding: 4px 6px; border-radius: 7px; font-size: 12px; color: var(--text); cursor: pointer;
|
|
1325
|
+
}
|
|
1326
|
+
.bp-build:hover { background: var(--code-bg); }
|
|
1327
|
+
.bp-build.on .bp-when { font-weight: 600; }
|
|
1328
|
+
.bp-when { min-width: 104px; white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|
1329
|
+
.bp-notes { margin-left: auto; color: var(--text-3); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1330
|
+
/* the history above, the graph on show and its files below */
|
|
1331
|
+
.bp-build + .pop-h, .bp-btns + .pop-h { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
|
|
1332
|
+
.pop-ok { padding: 4px; }
|
|
1333
|
+
.pf {
|
|
1334
|
+
display: flex; align-items: center; gap: 8px; width: 100%; border: 0; background: transparent; text-align: left;
|
|
1335
|
+
padding: 4px 6px; border-radius: 7px; font-size: 12px;
|
|
1336
|
+
}
|
|
1337
|
+
.pf:hover { background: var(--code-bg); }
|
|
1338
|
+
.pf-name { flex: 1; font-family: var(--mono); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1339
|
+
.pf-st { color: var(--text-3); font-size: 11px; white-space: nowrap; }
|
|
1340
|
+
.o-st { width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block; background: var(--st-stale); }
|
|
1341
|
+
.o-st.st-failed, .o-st.st-unbuilt { background: var(--st-failed); }
|
|
1342
|
+
.o-st.st-sorry { background: var(--st-sorry); }
|
|
1343
|
+
.o-st.st-building { background: var(--st-building); animation: pulse 1.1s ease-in-out infinite; }
|
|
1344
|
+
.o-st.st-blocked { background: transparent; box-shadow: inset 0 0 0 1.5px var(--st-failed); }
|
|
1345
|
+
.o-st.st-stale, .o-st.st-queued { background: transparent; box-shadow: inset 0 0 0 1.5px var(--st-stale); }
|
|
1346
|
+
.banner { border-radius: 10px; padding: 8px 10px; font-size: 12px; margin: 0 0 10px; line-height: 1.4; }
|
|
1347
|
+
.banner.bad { background: rgba(255, 59, 48, 0.1); color: var(--banner-bad); }
|
|
1348
|
+
.banner.warn { background: rgba(255, 159, 10, 0.13); color: var(--banner-warn); }
|
|
1349
|
+
.banner.info { background: rgba(10, 132, 255, 0.1); color: var(--banner-info); }
|
|
1350
|
+
.banner code { font: 11px var(--mono); }
|
|
1351
|
+
.tip-st { font: 600 10.5px var(--font); margin-left: 6px; color: var(--text-2); }
|
|
1352
|
+
.tip-st.st-failed, .tip-st.st-unbuilt, .tip-st.st-blocked { color: var(--st-failed); }
|
|
1353
|
+
.tip-st.st-sorry { color: var(--st-sorry); }
|
|
1354
|
+
.tip-st.st-building { color: var(--st-building); }
|
|
1355
|
+
.right { display: flex; align-items: center; gap: 10px; flex: 1; justify-content: flex-end; }
|
|
1356
|
+
|
|
1357
|
+
.seg { display: flex; background: var(--code-bg); border-radius: 10px; padding: 2px; }
|
|
1358
|
+
.seg button {
|
|
1359
|
+
border: 0; background: transparent; padding: 5px 13px; border-radius: 8px;
|
|
1360
|
+
font-weight: 500; color: var(--text-2); transition: background 0.15s, color 0.15s;
|
|
1361
|
+
}
|
|
1362
|
+
.seg button:hover { color: var(--text); }
|
|
1363
|
+
.seg button.on { background: var(--surface-solid); color: var(--text); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); }
|
|
1364
|
+
.seg.small button { padding: 4px 10px; font-size: 12px; }
|
|
1365
|
+
|
|
1366
|
+
.search-wrap { position: relative; }
|
|
1367
|
+
#search {
|
|
1368
|
+
width: 220px; height: 32px; border-radius: 9px; border: 0.5px solid var(--line);
|
|
1369
|
+
background: var(--code-bg); color: var(--text); padding: 0 12px; font: inherit; outline: none;
|
|
1370
|
+
}
|
|
1371
|
+
#search:focus { background: var(--surface-solid); box-shadow: 0 0 0 3px rgba(125, 92, 240, 0.25); }
|
|
1372
|
+
/* the search asked for a declaration (the lost-and-found's Attach to…): it says so */
|
|
1373
|
+
.search-wrap.picking #search { width: 300px; box-shadow: 0 0 0 2px var(--accent); }
|
|
1374
|
+
.search-wrap.picking #search::placeholder { color: var(--accent); }
|
|
1375
|
+
#results {
|
|
1376
|
+
position: absolute; right: 0; top: 40px; width: min(500px, calc(100vw - 24px)); max-height: min(560px, calc(100vh - 80px)); overflow: auto;
|
|
1377
|
+
border-radius: 12px; padding: 4px;
|
|
1378
|
+
/* denser than the other glass: snippets are read, and the labels of the canvas would show through */
|
|
1379
|
+
background: color-mix(in srgb, var(--surface-solid) 94%, transparent);
|
|
1380
|
+
}
|
|
1381
|
+
/* a result: its name, and where it matched when that is not the name (web/src/search.ts) */
|
|
1382
|
+
.hit { padding: 6px 10px; border-radius: 8px; cursor: pointer; }
|
|
1383
|
+
.hit.on, .hit:hover { background: var(--code-bg); }
|
|
1384
|
+
.h-line { display: flex; align-items: center; gap: 8px; white-space: nowrap; min-width: 0; }
|
|
1385
|
+
.h-name { font-weight: 600; }
|
|
1386
|
+
.h-ns { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; font-size: 12px; }
|
|
1387
|
+
/* under the name, in line with it past the dot */
|
|
1388
|
+
.h-snip { display: flex; align-items: baseline; gap: 7px; margin: 2px 0 0 16px; min-width: 0; color: var(--text-2); font-size: 12px; }
|
|
1389
|
+
.h-where { flex: none; font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-3); }
|
|
1390
|
+
.h-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
1391
|
+
.h-statement .h-text { font: 11.5px var(--mono); }
|
|
1392
|
+
#results mark { background: color-mix(in srgb, var(--accent) 24%, transparent); color: inherit; border-radius: 3px; }
|
|
1393
|
+
.h-more, .h-none { padding: 7px 10px 5px; color: var(--text-2); font-size: 11.5px; }
|
|
1394
|
+
.h-more { border-top: 1px solid var(--line); margin-top: 4px; }
|
|
1395
|
+
|
|
1396
|
+
.hint {
|
|
1397
|
+
position: fixed; top: 112px; left: calc((100vw + var(--inset-left, 0px) - var(--inset-right, 0px)) / 2); transform: translateX(-50%);
|
|
1398
|
+
color: var(--text-2); font-size: 12px; z-index: 5; pointer-events: none; white-space: nowrap;
|
|
1399
|
+
transition: left 0.32s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
1400
|
+
}
|
|
1401
|
+
/* something said for a moment (a shift-click that changed nothing): read, then gone */
|
|
1402
|
+
/* something said for a moment is read above the floating windows too: it answers what was just done */
|
|
1403
|
+
.hint.say { color: var(--text); padding: 3px 10px; border-radius: 8px; background: var(--surface-solid); box-shadow: var(--shadow); z-index: 36; }
|
|
1404
|
+
.hint.say.below { top: 156px; }
|
|
1405
|
+
|
|
1406
|
+
/* the selection (web/src/selbar.ts): under the modes, heading the panel's column */
|
|
1407
|
+
#selbar {
|
|
1408
|
+
position: fixed; top: 106px; right: 12px; width: 400px; max-width: calc(100vw - 24px); z-index: 7;
|
|
1409
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 6px 8px; border-radius: 12px;
|
|
1410
|
+
max-height: 96px; overflow: auto;
|
|
1411
|
+
}
|
|
1412
|
+
.sb-chips { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; flex: 1 1 auto; }
|
|
1413
|
+
.sb-chip {
|
|
1414
|
+
display: inline-flex; align-items: center; max-width: 100%; min-height: 24px; padding: 0 2px 0 0; border-radius: 999px;
|
|
1415
|
+
border: 1px solid var(--line); background: var(--surface-solid); font: 12px/1.3 var(--font);
|
|
1416
|
+
}
|
|
1417
|
+
.sb-chip.on { border-color: color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }
|
|
1418
|
+
.sb-go {
|
|
1419
|
+
min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border: 0; background: transparent; padding: 2px 4px 2px 9px;
|
|
1420
|
+
color: var(--text); font: inherit; cursor: pointer;
|
|
1421
|
+
}
|
|
1422
|
+
.sb-go:hover:not(:disabled) { color: var(--accent); }
|
|
1423
|
+
.sb-go:disabled { color: var(--text-2); cursor: default; font-style: italic; }
|
|
1424
|
+
.sb-chip.on .sb-go { color: var(--accent); font-weight: 600; }
|
|
1425
|
+
.sb-x { flex: none; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-3); font-size: 13px; line-height: 1; cursor: pointer; }
|
|
1426
|
+
.sb-x:hover { background: var(--code-bg); color: var(--bad); }
|
|
1427
|
+
.sb-meta { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }
|
|
1428
|
+
.sb-n { color: var(--text-2); font-size: 11.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
1429
|
+
.sb-btn {
|
|
1430
|
+
height: 24px; padding: 0 8px; border-radius: 7px; border: 1px solid var(--line); background: var(--surface-solid);
|
|
1431
|
+
color: var(--text-2); font: 500 11.5px var(--font); white-space: nowrap; cursor: pointer;
|
|
1432
|
+
}
|
|
1433
|
+
.sb-btn:hover:not(:disabled) { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
|
|
1434
|
+
.sb-btn:disabled { color: var(--text-3); cursor: default; }
|
|
1435
|
+
|
|
1436
|
+
/* ---------------------------------------------------------------- the top: tabs and light-up */
|
|
1437
|
+
|
|
1438
|
+
#viewbar {
|
|
1439
|
+
position: fixed; top: 66px; left: 12px; right: 12px; height: 34px; z-index: 17;
|
|
1440
|
+
display: flex; align-items: center; gap: 8px; pointer-events: none;
|
|
1441
|
+
}
|
|
1442
|
+
#viewbar > * { pointer-events: auto; }
|
|
1443
|
+
.tabs { display: flex; align-items: center; gap: 4px; min-width: 0; overflow-x: auto; scrollbar-width: none; padding: 2px; }
|
|
1444
|
+
.tabs::-webkit-scrollbar { display: none; }
|
|
1445
|
+
.tab, .views-btn {
|
|
1446
|
+
flex: none; display: inline-flex; align-items: center; gap: 6px; height: 30px; max-width: 240px; padding: 0 6px 0 12px;
|
|
1447
|
+
border-radius: 10px; border: 0.5px solid var(--line); background: var(--surface); color: var(--text-2);
|
|
1448
|
+
backdrop-filter: saturate(180%) blur(22px); -webkit-backdrop-filter: saturate(180%) blur(22px);
|
|
1449
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06); font: 500 12.5px var(--font); white-space: nowrap; cursor: pointer;
|
|
1450
|
+
transition: background 0.15s, color 0.15s, box-shadow 0.15s;
|
|
1451
|
+
}
|
|
1452
|
+
.tab:hover, .views-btn:hover { color: var(--text); }
|
|
1453
|
+
.tab.on { background: var(--surface-solid); color: var(--text); box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--accent) 55%, transparent), var(--shadow); }
|
|
1454
|
+
.tab-t { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
1455
|
+
/* a view nobody keeps: it goes when the last page closes it */
|
|
1456
|
+
.tab.loose .tab-t { font-style: italic; }
|
|
1457
|
+
.tab .star { margin-right: 3px; }
|
|
1458
|
+
/* a view targets are linked to (ViewSpec decision 29): a small yellow star by its name, on its tab
|
|
1459
|
+
and in the Views menu */
|
|
1460
|
+
.link-star { font-size: 0.82em; vertical-align: 0.08em; }
|
|
1461
|
+
.vm-link { width: 100%; margin-bottom: 6px; }
|
|
1462
|
+
.vm-link .star { margin-right: 1px; }
|
|
1463
|
+
.rv-view { margin-top: 8px; font-size: 12px; }
|
|
1464
|
+
.rv-view b { color: var(--text); font-weight: 500; }
|
|
1465
|
+
/* a tab that cannot be closed (the Project) is as wide on the right as on the left */
|
|
1466
|
+
.tab:not(:has(.tab-x)) { padding-right: 12px; }
|
|
1467
|
+
.tab-x { display: grid; place-items: center; width: 18px; height: 18px; border-radius: 6px; color: var(--text-3); font-size: 14px; line-height: 1; }
|
|
1468
|
+
.tab-x:hover { background: var(--code-bg); color: var(--text); }
|
|
1469
|
+
.views-wrap { position: relative; flex: none; }
|
|
1470
|
+
.views-btn { padding: 0 10px 0 12px; }
|
|
1471
|
+
.views-btn svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1472
|
+
.views-btn.on { color: var(--accent); background: var(--surface-solid); }
|
|
1473
|
+
#views-menu {
|
|
1474
|
+
position: absolute; top: 38px; left: 0; width: min(360px, calc(100vw - 24px)); max-height: calc(100vh - 130px); overflow: auto;
|
|
1475
|
+
border-radius: 14px; padding: 8px; z-index: 30; background: color-mix(in srgb, var(--surface-solid) 94%, transparent);
|
|
1476
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
1477
|
+
}
|
|
1478
|
+
.vm-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 6px; }
|
|
1479
|
+
.vm-act {
|
|
1480
|
+
height: 28px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface-solid); color: var(--text);
|
|
1481
|
+
font: 500 12px var(--font); cursor: pointer;
|
|
1482
|
+
}
|
|
1483
|
+
.vm-act:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
|
|
1484
|
+
.vm-act.bad:hover:not(:disabled) { border-color: var(--bad); color: var(--bad); }
|
|
1485
|
+
.vm-act:disabled { color: var(--text-3); cursor: default; }
|
|
1486
|
+
.vm-h { margin: 10px 6px 4px; font-size: 11px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
1487
|
+
.vm-row {
|
|
1488
|
+
display: flex; flex-direction: column; align-items: stretch; width: 100%; border: 0; background: transparent; text-align: left;
|
|
1489
|
+
padding: 4px 6px; border-radius: 7px; cursor: pointer; color: var(--text); font: 12.5px var(--font);
|
|
1490
|
+
}
|
|
1491
|
+
.vm-row:hover, .vm-row.on { background: var(--code-bg); }
|
|
1492
|
+
.vm-row.on { box-shadow: inset 2px 0 0 var(--accent); }
|
|
1493
|
+
.vm-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
|
|
1494
|
+
/* in the Views menu, a view nobody keeps, in italics as its tab is */
|
|
1495
|
+
.vm-row.loose .vm-name { font-style: italic; }
|
|
1496
|
+
.vm-scope { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 11px var(--mono); color: var(--text-3); }
|
|
1497
|
+
.vm-note { padding: 8px 6px 2px; font-size: 11.5px; }
|
|
1498
|
+
.vm-ask { display: flex; flex-direction: column; gap: 6px; padding: 4px; }
|
|
1499
|
+
.vm-l { font-size: 12px; color: var(--text-2); }
|
|
1500
|
+
.vm-input {
|
|
1501
|
+
font: 13px var(--font); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line); border-radius: 8px; padding: 7px 10px;
|
|
1502
|
+
}
|
|
1503
|
+
.vm-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
1504
|
+
.vm-actions { display: flex; justify-content: flex-end; gap: 6px; }
|
|
1505
|
+
/* the review's focus, in the view's header (ViewSpec decision 28; web/src/focus.ts): the reader's own
|
|
1506
|
+
focus, where it is not the view's, says so */
|
|
1507
|
+
.focus-wrap { position: relative; flex: none; }
|
|
1508
|
+
.focus-btn { gap: 3px; max-width: 280px; }
|
|
1509
|
+
.focus-btn .fc-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
1510
|
+
.focus-btn svg { flex: none; }
|
|
1511
|
+
.focus-btn .fc-k { color: var(--text-3); font-weight: 500; }
|
|
1512
|
+
.focus-btn .star { margin-right: 1px; }
|
|
1513
|
+
.focus-btn .fc-own { margin-left: 2px; color: var(--accent); font-size: 11px; font-weight: 600; }
|
|
1514
|
+
.focus-btn.own { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
1515
|
+
#focus-menu {
|
|
1516
|
+
position: absolute; top: 38px; left: 0; width: min(300px, calc(100vw - 24px)); max-height: calc(100vh - 130px); overflow: auto;
|
|
1517
|
+
border-radius: 14px; padding: 8px; z-index: 30; background: color-mix(in srgb, var(--surface-solid) 94%, transparent);
|
|
1518
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
1519
|
+
}
|
|
1520
|
+
#focus-menu .vm-h .muted { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: 4px; }
|
|
1521
|
+
.fc-row { flex-direction: row; align-items: center; gap: 6px; }
|
|
1522
|
+
.fc-dot { flex: none; width: 12px; color: var(--accent); font-size: 10px; }
|
|
1523
|
+
.fc-note { margin-left: auto; font-size: 11px; }
|
|
1524
|
+
.fc-back, .fc-set { width: 100%; margin-top: 6px; }
|
|
1525
|
+
.vm-sep { height: 1px; margin: 8px 2px 2px; background: var(--line); }
|
|
1526
|
+
.vb-gap { flex: 1; }
|
|
1527
|
+
.light-l { flex: none; font-size: 11.5px; color: var(--text-2); }
|
|
1528
|
+
/* what a mode does, under its button while the pointer is on it */
|
|
1529
|
+
.mode-tip {
|
|
1530
|
+
position: fixed; z-index: 40; max-width: 280px; padding: 7px 10px; border-radius: 10px;
|
|
1531
|
+
font-size: 12px; line-height: 1.45; color: var(--text); pointer-events: none;
|
|
1532
|
+
}
|
|
1533
|
+
.mode-tip[hidden] { display: none; }
|
|
1534
|
+
.mode-tip div { color: var(--text-2); margin-top: 2px; }
|
|
1535
|
+
/* Rests on's steps in the tip: one line each */
|
|
1536
|
+
.mode-tip .tip-steps { margin: 4px 0 0; padding: 0 0 0 14px; color: var(--text-2); }
|
|
1537
|
+
.mode-tip .tip-steps b { color: var(--text); font-weight: 600; }
|
|
1538
|
+
/* Rests on (ViewSpec decision 20): one segment of the bar, which while it is the mode holds its
|
|
1539
|
+
three steps beside its name, the step in force in the accent colour */
|
|
1540
|
+
#lightup .rests { display: flex; align-items: center; border-radius: 8px; transition: background 0.15s, box-shadow 0.15s; }
|
|
1541
|
+
#lightup .rests.on { background: var(--surface-solid); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); }
|
|
1542
|
+
#lightup .rests.on > button { color: var(--text); padding-right: 6px; }
|
|
1543
|
+
#lightup .steps { display: flex; align-items: center; gap: 1px; margin-right: 3px; padding: 1px; border-radius: 7px; background: var(--code-bg); }
|
|
1544
|
+
#lightup .steps[hidden] { display: none; }
|
|
1545
|
+
#lightup .steps button { padding: 2px 8px; border-radius: 6px; font-size: 11.5px; }
|
|
1546
|
+
#lightup .steps button.on { color: var(--accent); background: var(--surface-solid); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent); font-weight: 600; }
|
|
1547
|
+
#lightup { flex: none; background: var(--surface); backdrop-filter: saturate(180%) blur(22px); -webkit-backdrop-filter: saturate(180%) blur(22px); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06); border: 0.5px solid var(--line); }
|
|
1548
|
+
|
|
1549
|
+
/* ---------------------------------------------------------------- side panels */
|
|
1550
|
+
|
|
1551
|
+
#side {
|
|
1552
|
+
position: fixed; top: 108px; left: 12px; bottom: 56px; width: 268px; overflow-x: hidden;
|
|
1553
|
+
border-radius: 16px; z-index: 6; display: flex; flex-direction: column; overflow: hidden;
|
|
1554
|
+
}
|
|
1555
|
+
/* a section of the side panel that folds away (the targets, the filter, the trusted list): its
|
|
1556
|
+
heading, a chevron, the title and what is worth seeing folded */
|
|
1557
|
+
.sec-h {
|
|
1558
|
+
display: flex; align-items: center; gap: 6px; width: 100%; padding: 2px 0; border: 0; background: transparent;
|
|
1559
|
+
color: var(--text); font: 600 12.5px var(--font); text-align: left; cursor: pointer;
|
|
1560
|
+
}
|
|
1561
|
+
.sec-chev { flex: none; width: 10px; color: var(--text-3); font-size: 10px; }
|
|
1562
|
+
.sec-t { flex: none; }
|
|
1563
|
+
.sec-aside { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; font-size: 11.5px; }
|
|
1564
|
+
.sec-h:hover .sec-chev, .sec-h:hover .sec-t { color: var(--accent); }
|
|
1565
|
+
/* the targets (web/src/targetlist.ts): at the top, the same on every board */
|
|
1566
|
+
#targets { padding: 10px 12px 8px 14px; border-bottom: 1px solid var(--line); flex: none; max-height: 30%; overflow: auto; }
|
|
1567
|
+
.tg-rows { display: flex; flex-direction: column; gap: 1px; margin-top: 4px; }
|
|
1568
|
+
.tg-row {
|
|
1569
|
+
display: grid; grid-template-columns: minmax(0, 1fr) 40px auto auto; align-items: center; gap: 7px; width: 100%;
|
|
1570
|
+
padding: 4px 6px; border: 0; border-radius: 7px; background: transparent; color: var(--text); text-align: left; cursor: pointer;
|
|
1571
|
+
}
|
|
1572
|
+
.tg-row:hover, .tg-row.on { background: var(--code-bg); }
|
|
1573
|
+
.tg-row.on { box-shadow: inset 2px 0 0 var(--accent); }
|
|
1574
|
+
.tg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 12px var(--mono); }
|
|
1575
|
+
.tg-name .star { margin-right: 3px; }
|
|
1576
|
+
/* a target with no view (ViewSpec decision 29, the owner's decision of 2026-10-11): said where its
|
|
1577
|
+
bar is; a click goes to it on the board on show */
|
|
1578
|
+
.tg-noview { font: 10.5px var(--font); color: var(--text-3); white-space: nowrap; }
|
|
1579
|
+
.tg-n { color: var(--text-2); font-size: 11.5px; font-variant-numeric: tabular-nums; }
|
|
1580
|
+
.tg-key { color: var(--text-2); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
1581
|
+
.tg-key .key-mark { margin-right: 1px; }
|
|
1582
|
+
.tg-gone { grid-column: 2 / 5; font-size: 11px; }
|
|
1583
|
+
.tg-none { margin-top: 4px; font-size: 11.5px; line-height: 1.4; }
|
|
1584
|
+
/* the board (web/src/boardpanel.ts): which view, kept or not, and its scope as chips */
|
|
1585
|
+
.board-h { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
|
|
1586
|
+
.board-k { flex: none; font-size: 10.5px; font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; }
|
|
1587
|
+
.board-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
1588
|
+
.board-tag { margin: 1px 0 8px; font-size: 11px; color: var(--text-2); }
|
|
1589
|
+
.board-tag.loose { color: var(--banner-warn); }
|
|
1590
|
+
.scope { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
|
|
1591
|
+
.schip {
|
|
1592
|
+
display: inline-flex; align-items: center; gap: 2px; max-width: 100%; min-height: 24px; padding: 2px 3px 2px 9px; border-radius: 999px;
|
|
1593
|
+
border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 11.5px/1.3 var(--font); cursor: default;
|
|
1594
|
+
}
|
|
1595
|
+
.schip.base { padding: 2px 9px; color: var(--accent); font-weight: 600; cursor: pointer; border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
|
|
1596
|
+
.schip.base:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface-solid)); }
|
|
1597
|
+
.schip.add { width: 24px; padding: 0; justify-content: center; color: var(--accent); font: 600 14px/1 var(--font); cursor: pointer; }
|
|
1598
|
+
.schip.add:hover, .schip.add.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--surface-solid)); }
|
|
1599
|
+
.schip-x { flex: none; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--text-3); font-size: 13px; line-height: 1; }
|
|
1600
|
+
.schip-x:hover { background: var(--code-bg); color: var(--bad); }
|
|
1601
|
+
.scope-add { display: flex; flex-direction: column; gap: 1px; margin-top: 6px; padding: 4px; border-radius: 10px; background: var(--code-bg); }
|
|
1602
|
+
.sa-row {
|
|
1603
|
+
border: 0; background: transparent; text-align: left; padding: 4px 8px; border-radius: 6px; font: 12px var(--font); color: var(--text); cursor: pointer;
|
|
1604
|
+
}
|
|
1605
|
+
.sa-row:hover:not(:disabled) { background: var(--surface-solid); color: var(--accent); }
|
|
1606
|
+
.sa-row:disabled { color: var(--text-3); cursor: default; }
|
|
1607
|
+
.sa-form input, .scope-input {
|
|
1608
|
+
width: 100%; font: 12px var(--font); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line);
|
|
1609
|
+
border-radius: 6px; padding: 4px 8px; margin: 2px 0;
|
|
1610
|
+
}
|
|
1611
|
+
.scope-input { font: 11.5px var(--mono); padding: 6px 8px; }
|
|
1612
|
+
.sa-form input:focus, .scope-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
1613
|
+
.scope-help { font-size: 11px; line-height: 1.4; margin: 2px 0 4px; }
|
|
1614
|
+
#board .sec-h { margin-bottom: 4px; }
|
|
1615
|
+
/* someone else changed the board: a short note, fading */
|
|
1616
|
+
.board-note {
|
|
1617
|
+
margin: 4px 0 2px; padding: 4px 8px; border-radius: 8px; font-size: 12px; line-height: 1.4;
|
|
1618
|
+
background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--text); transition: opacity 0.6s;
|
|
1619
|
+
}
|
|
1620
|
+
.board-note.fade, .note.fade { opacity: 0; }
|
|
1621
|
+
/* the cluster controls: a label column, and one row each for depth, what is shown, the view */
|
|
1622
|
+
/* over the cluster tree: what it is clustered by, and the two buttons that open the rest beside the
|
|
1623
|
+
side panel (web/src/popover.ts) */
|
|
1624
|
+
.side-tools { display: flex; align-items: center; gap: 4px; padding: 8px 10px 6px 14px; flex: none; }
|
|
1625
|
+
.side-what { flex: 1; min-width: 0; font: 600 12.5px var(--font); }
|
|
1626
|
+
.side-tool { display: inline-flex; align-items: center; gap: 4px; }
|
|
1627
|
+
.side-tool.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); background: color-mix(in srgb, var(--accent) 9%, var(--surface-solid)); }
|
|
1628
|
+
.side-n { color: var(--text-3); font-variant-numeric: tabular-nums; }
|
|
1629
|
+
.side-tools + .board-note { margin: 0 12px 6px 14px; }
|
|
1630
|
+
.side-pop {
|
|
1631
|
+
position: fixed; z-index: 36; width: 284px; overflow: auto; padding: 12px 12px 12px 14px; border-radius: 14px;
|
|
1632
|
+
background: color-mix(in srgb, var(--surface-solid) 94%, transparent); box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
1633
|
+
}
|
|
1634
|
+
#board-pop .ctl { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
|
|
1635
|
+
.side-title { font-weight: 600; margin-bottom: 8px; }
|
|
1636
|
+
.ctl { display: grid; grid-template-columns: 50px minmax(0, 1fr); align-items: center; gap: 6px 6px; }
|
|
1637
|
+
.ctl-l { font-size: 11.5px; color: var(--text-2); }
|
|
1638
|
+
.ctl-r { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-width: 0; }
|
|
1639
|
+
#hidden-levels { font-size: 11.5px; color: var(--text-2); }
|
|
1640
|
+
.hl-list { display: flex; flex-direction: column; gap: 1px; margin: 6px 0 0 56px; max-height: 160px; overflow: auto; font-size: 11.5px; }
|
|
1641
|
+
.hl-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
1642
|
+
.hl-key { flex: 1; min-width: 0; font: 11px var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-2); }
|
|
1643
|
+
.sbtn {
|
|
1644
|
+
height: 24px; padding: 0 8px; border-radius: 7px; border: 1px solid var(--line); background: var(--surface-solid);
|
|
1645
|
+
color: var(--text-2); font: 500 11.5px var(--font); white-space: nowrap; cursor: pointer;
|
|
1646
|
+
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
|
1647
|
+
}
|
|
1648
|
+
.sbtn:hover { color: var(--text); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
|
|
1649
|
+
.sbtn.toggle.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 11%, var(--surface-solid)); border-color: color-mix(in srgb, var(--accent) 38%, transparent); }
|
|
1650
|
+
.stepper {
|
|
1651
|
+
display: inline-flex; align-items: stretch; height: 24px; border: 1px solid var(--line); border-radius: 7px;
|
|
1652
|
+
background: var(--surface-solid); overflow: hidden;
|
|
1653
|
+
}
|
|
1654
|
+
.stepper button { width: 26px; padding: 0; border: 0; background: transparent; color: var(--text); font: 500 14px/1 var(--font); cursor: pointer; }
|
|
1655
|
+
.stepper button:hover:not(:disabled) { background: var(--code-bg); color: var(--accent); }
|
|
1656
|
+
.stepper button:disabled { color: var(--text-3); cursor: default; }
|
|
1657
|
+
#fold-level {
|
|
1658
|
+
display: grid; place-items: center; min-width: 58px; padding: 0 6px; border-inline: 1px solid var(--line);
|
|
1659
|
+
font-size: 11.5px; color: var(--text); font-variant-numeric: tabular-nums;
|
|
1660
|
+
}
|
|
1661
|
+
#outline { overflow: auto; padding: 0 6px 10px; flex: 1; }
|
|
1662
|
+
.o-row { display: flex; align-items: center; gap: 4px; height: 26px; border-radius: 7px; cursor: pointer; padding-right: 4px; }
|
|
1663
|
+
.o-row:hover { background: var(--code-bg); }
|
|
1664
|
+
/* a cluster the selection picked */
|
|
1665
|
+
.o-row.on { background: color-mix(in srgb, var(--accent) 11%, transparent); box-shadow: inset 2px 0 0 var(--accent); }
|
|
1666
|
+
.o-row.on .o-label { color: var(--accent); font-weight: 600; }
|
|
1667
|
+
.o-row .tw { width: 12px; color: var(--text-3); font-size: 10px; flex: none; text-align: center; }
|
|
1668
|
+
.o-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1669
|
+
.o-count { color: var(--text-3); font-size: 11px; font-variant-numeric: tabular-nums; }
|
|
1670
|
+
.o-row .fold { border: 0; background: transparent; color: var(--text-2); width: 20px; padding: 0; font-size: 10px; }
|
|
1671
|
+
.o-row .fold:hover { color: var(--accent); }
|
|
1672
|
+
.o-row.folded .o-label, .o-row.folded .o-count { color: var(--text-3); }
|
|
1673
|
+
.o-row.folded .fold { color: var(--text-3); }
|
|
1674
|
+
|
|
1675
|
+
#panel {
|
|
1676
|
+
position: fixed; top: calc(108px + var(--selbar-h, 0px)); right: 12px; bottom: 56px; width: 400px;
|
|
1677
|
+
border-radius: 18px; z-index: 6; overflow: auto; padding: 18px 20px 24px;
|
|
1678
|
+
transform: translateX(calc(100% + 24px)); transition: transform 0.32s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
1679
|
+
}
|
|
1680
|
+
#panel.open { transform: none; }
|
|
1681
|
+
.p-head { display: flex; justify-content: space-between; align-items: center; }
|
|
1682
|
+
.p-kind { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; color: var(--text-2); font-size: 12px; font-weight: 500; text-transform: capitalize; }
|
|
1683
|
+
.icon { border: 0; background: var(--code-bg); border-radius: 50%; width: 26px; height: 26px; color: var(--text-2); }
|
|
1684
|
+
.p-name {
|
|
1685
|
+
margin: 8px 0 2px; font-size: 26px; line-height: 1.15; letter-spacing: -0.025em; font-weight: 700;
|
|
1686
|
+
background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent;
|
|
1687
|
+
word-break: break-word;
|
|
1688
|
+
}
|
|
1689
|
+
.p-ns { color: var(--text-2); font-size: 12.5px; word-break: break-all; }
|
|
1690
|
+
.p-mod { color: var(--text-3); font-size: 12px; margin: 6px 0 12px; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
|
|
1691
|
+
.p-gen { color: var(--text-2); font-size: 12px; margin: -6px 0 12px; line-height: 1.45; }
|
|
1692
|
+
.sw-print { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
|
|
1693
|
+
.sw-print-h { color: var(--text-3); font-size: 12px; margin-bottom: 6px; font-family: var(--mono, ui-monospace, monospace); }
|
|
1694
|
+
.p-decl { font-family: var(--mono); font-size: 11.5px; cursor: help; }
|
|
1695
|
+
/* the context a declaration is written in, above its code (shared/context.ts) */
|
|
1696
|
+
.sw-ctx { margin: 0 0 10px; padding: 0 0 8px; border-bottom: 1px dashed var(--line); }
|
|
1697
|
+
.sw-ctx .code { font: 11.5px/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; background: transparent; padding: 0; margin: 0; border-radius: 0; }
|
|
1698
|
+
.sw-ctx-l { opacity: 0.55; }
|
|
1699
|
+
.sw-ctx-l.used { opacity: 0.95; box-shadow: inset 2px 0 0 var(--accent); padding-left: 6px; margin-left: -8px; }
|
|
1700
|
+
.sw-ctx:not(.open) .sw-ctx-l.fold { display: none; }
|
|
1701
|
+
.sw-ctx-more { font-size: 11.5px; margin-top: 2px; }
|
|
1702
|
+
.sw-gen-row { margin: 4px 0; }
|
|
1703
|
+
.sw-gen-row pre.code { margin: 4px 0 10px; }
|
|
1704
|
+
/* what Lean's #print says wraps as the code does */
|
|
1705
|
+
.sw-print pre.code { overflow-wrap: anywhere; }
|
|
1706
|
+
/* what Lean says of a generated declaration comes after the window stands at the size its code
|
|
1707
|
+
gives it: it wraps to that width, never widening the window (nor moving the reference beside it) */
|
|
1708
|
+
.sw-win [data-sw-print] { contain: inline-size; }
|
|
1709
|
+
.sw-gen-name { font: 12px var(--mono); }
|
|
1710
|
+
.sw-gen-cmd { color: var(--text-3); }
|
|
1711
|
+
.link { border: 0; background: none; padding: 0; color: var(--accent); font-weight: 500; font-size: 12px; }
|
|
1712
|
+
/* "Open in editor" is a real link (web/src/editor.ts), drawn like the buttons beside it */
|
|
1713
|
+
a.link { text-decoration: none; white-space: nowrap; }
|
|
1714
|
+
a.link:hover { text-decoration: underline; }
|
|
1715
|
+
.sw-head .editor-link { align-self: center; flex: none; }
|
|
1716
|
+
.code {
|
|
1717
|
+
font: 12px/1.55 var(--mono); background: var(--code-bg); border-radius: 10px;
|
|
1718
|
+
padding: 10px 12px; margin: 0 0 12px; white-space: pre-wrap; word-break: break-word;
|
|
1719
|
+
}
|
|
1720
|
+
.doc { color: var(--text); font-size: 13px; margin-bottom: 12px; }
|
|
1721
|
+
.doc p { margin: 0 0 8px; }
|
|
1722
|
+
.doc code { font: 12px var(--mono); background: var(--code-bg); padding: 1px 4px; border-radius: 4px; }
|
|
1723
|
+
|
|
1724
|
+
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 6px 0 14px; }
|
|
1725
|
+
.stat { background: var(--code-bg); border-radius: 12px; padding: 10px 12px; }
|
|
1726
|
+
.stat .n { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; -webkit-background-clip: text; background-clip: text; color: transparent; font-variant-numeric: tabular-nums; }
|
|
1727
|
+
.grad-tcb { background-image: var(--grad-tcb); }
|
|
1728
|
+
.grad-dep { background-image: var(--grad-dep); }
|
|
1729
|
+
.grad-app { background-image: var(--grad-app); }
|
|
1730
|
+
.grad-name { background-image: var(--grad); }
|
|
1731
|
+
.stat .l { color: var(--text-2); font-size: 11.5px; line-height: 1.3; }
|
|
1732
|
+
.sec { font-weight: 600; margin: 10px 0 6px; }
|
|
1733
|
+
/* a part of the panel that folds (web/src/panel.ts): its heading, and what it holds while open */
|
|
1734
|
+
.p-sec { border-top: 1px solid var(--line); padding: 7px 0 3px; }
|
|
1735
|
+
.p-sec .sec-h { padding: 2px 0; }
|
|
1736
|
+
.p-sec .sec-aside { flex: 1; text-align: right; }
|
|
1737
|
+
.p-sec .sec-aside .chip { margin: 0; }
|
|
1738
|
+
.p-sec-body { padding-top: 6px; }
|
|
1739
|
+
.p-sec-body .why, .p-sec-body .stats, .p-sec-body .axioms { margin-top: 0; }
|
|
1740
|
+
.p-order { margin-bottom: 4px; }
|
|
1741
|
+
.axioms { margin-bottom: 8px; }
|
|
1742
|
+
.chip {
|
|
1743
|
+
display: inline-block; padding: 1px 8px; border-radius: 999px; background: var(--code-bg);
|
|
1744
|
+
font-size: 11px; margin: 0 4px 4px 0; text-transform: none; color: var(--text-2);
|
|
1745
|
+
}
|
|
1746
|
+
.chip.warn { color: #c25400; background: rgba(255, 159, 10, 0.14); }
|
|
1747
|
+
.chip.bad { color: #d70015; background: rgba(255, 55, 95, 0.14); font-weight: 600; }
|
|
1748
|
+
.muted { color: var(--text-3); font-weight: 400; }
|
|
1749
|
+
.grp { margin-bottom: 8px; }
|
|
1750
|
+
.grp-h { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--text-2); text-transform: capitalize; margin: 6px 0 2px; }
|
|
1751
|
+
.row {
|
|
1752
|
+
display: block; width: 100%; text-align: left; border: 0; background: transparent; padding: 3px 8px;
|
|
1753
|
+
border-radius: 6px; font: 12px var(--mono); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
1754
|
+
}
|
|
1755
|
+
.row:hover { background: var(--code-bg); }
|
|
1756
|
+
/* a cluster's panel (web/src/clusterpanel.ts) */
|
|
1757
|
+
.cp-kinds { display: flex; flex-wrap: wrap; margin: -6px 0 6px; }
|
|
1758
|
+
.cp-kind { display: inline-flex; align-items: center; gap: 5px; text-transform: none; }
|
|
1759
|
+
.cp-kind b { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
|
|
1760
|
+
.cp-trust { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; line-height: 1.4; padding: 8px 10px; background: var(--code-bg); border-radius: 10px; }
|
|
1761
|
+
.cp-trust > span:not(.cp-shield) { flex: 1 1 200px; }
|
|
1762
|
+
.cp-trust code { font: 11.5px var(--mono); }
|
|
1763
|
+
.cp-shield { display: inline-grid; place-items: center; width: 20px; height: 20px; color: var(--text-3); flex: none; }
|
|
1764
|
+
.cp-shield svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }
|
|
1765
|
+
.cp-shield.on { color: var(--rv-trusted); }
|
|
1766
|
+
.cp-shield.on svg { fill: color-mix(in srgb, var(--rv-trusted) 35%, transparent); }
|
|
1767
|
+
.cp-shield.under { opacity: 0.6; }
|
|
1768
|
+
.cp-list { display: flex; flex-direction: column; }
|
|
1769
|
+
.cp-kid { display: flex; align-items: center; gap: 6px; font-family: var(--font); font-size: 12.5px; }
|
|
1770
|
+
.cp-kid .cp-l { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
1771
|
+
.cp-kid .cp-n { color: var(--text-3); font-size: 11px; font-variant-numeric: tabular-nums; }
|
|
1772
|
+
.cp-kid.folded .cp-l { color: var(--text-2); }
|
|
1773
|
+
.cp-mod { display: flex; align-items: center; gap: 6px; }
|
|
1774
|
+
.cp-note { font-size: 12px; margin: 4px 0; }
|
|
1775
|
+
|
|
1776
|
+
/* ---------------------------------------------------------------- cards on the canvas */
|
|
1777
|
+
|
|
1778
|
+
.card {
|
|
1779
|
+
position: absolute; left: 0; top: 0; pointer-events: auto; cursor: pointer;
|
|
1780
|
+
background: var(--surface-solid); border-radius: 12px; box-shadow: var(--shadow);
|
|
1781
|
+
border: 0.5px solid var(--line); padding: 5px 10px; max-width: 260px; user-select: none;
|
|
1782
|
+
will-change: transform;
|
|
1783
|
+
}
|
|
1784
|
+
.card:hover, .card.hover { box-shadow: 0 0 0 2px var(--accent), var(--shadow-lg); }
|
|
1785
|
+
.dot.cluster-dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--accent); }
|
|
1786
|
+
.card-head { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
|
|
1787
|
+
.card-name { font-weight: 600; font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
|
|
1788
|
+
.card-kind { color: var(--text-3); font-size: 10.5px; }
|
|
1789
|
+
.card.pinned::after {
|
|
1790
|
+
content: ""; position: absolute; top: -3px; right: -3px; width: 8px; height: 8px; border-radius: 50%;
|
|
1791
|
+
background: var(--grad); box-shadow: 0 0 0 2px var(--surface-solid);
|
|
1792
|
+
}
|
|
1793
|
+
.card.k-external { background: var(--surface); border-style: dashed; }
|
|
1794
|
+
.card.k-external .card-name { color: var(--text-2); font-weight: 500; }
|
|
1795
|
+
.cluster-card { border-radius: 999px; }
|
|
1796
|
+
/* a folded cluster selected, or holding what is: the selection's ring is its card's outline */
|
|
1797
|
+
.cluster-card.picked { box-shadow: 0 0 0 2px var(--surface-solid), 0 0 0 4px var(--accent), var(--shadow); }
|
|
1798
|
+
.cluster-card .card-name { color: var(--accent); }
|
|
1799
|
+
|
|
1800
|
+
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; background: var(--k-external); }
|
|
1801
|
+
.k-def .dot, .dot.k-def { background: var(--k-def); }
|
|
1802
|
+
.k-abbrev .dot, .dot.k-abbrev { background: var(--k-abbrev); }
|
|
1803
|
+
.k-structure .dot, .dot.k-structure { background: var(--k-structure); }
|
|
1804
|
+
.k-class .dot, .dot.k-class { background: var(--k-class); }
|
|
1805
|
+
.k-inductive .dot, .dot.k-inductive { background: var(--k-inductive); }
|
|
1806
|
+
.k-instance .dot, .dot.k-instance { background: var(--k-instance); }
|
|
1807
|
+
.k-theorem .dot, .dot.k-theorem { background: var(--k-theorem); }
|
|
1808
|
+
.k-opaque .dot, .dot.k-opaque { background: var(--k-opaque); }
|
|
1809
|
+
.k-axiom .dot, .dot.k-axiom { background: var(--k-axiom); }
|
|
1810
|
+
.k-notation .dot, .dot.k-notation { background: var(--k-notation); }
|
|
1811
|
+
/* the notation a declaration is written in (panel.ts, notationHtml) */
|
|
1812
|
+
.p-notation .row { display: flex; align-items: center; gap: 6px; }
|
|
1813
|
+
.p-notation .row .muted { margin-left: auto; font-size: 11px; }
|
|
1814
|
+
.p-notation .row.p-proof-only { opacity: 0.6; }
|
|
1815
|
+
/* grammar: the syntax a text is written with, outside the TCB (TCBSpec decision 2) */
|
|
1816
|
+
.p-notation .p-grammar-h { font-size: 11px; margin: 6px 0 2px; }
|
|
1817
|
+
.p-notation .row.p-grammar { opacity: 0.55; font-size: 11.5px; }
|
|
1818
|
+
.p-interprets .p-ref { font-family: var(--mono); font-size: 11.5px; }
|
|
1819
|
+
.p-lean code { font-size: 11px; word-break: break-all; }
|
|
1820
|
+
.sw-interprets { margin: 6px 0 0; padding: 0 14px; }
|
|
1821
|
+
.k-external .dot, .dot.k-external { background: transparent; box-shadow: inset 0 0 0 1.5px var(--k-external); }
|
|
1822
|
+
/* the Status scheme's dots (web/src/status.ts), on cards, in the tip and the legend: as on the
|
|
1823
|
+
canvas, the outside world a ring */
|
|
1824
|
+
.s-failed { --s: var(--status-failed); }
|
|
1825
|
+
.s-building { --s: var(--status-building); }
|
|
1826
|
+
.s-sorry { --s: var(--status-sorry); }
|
|
1827
|
+
.s-commented { --s: var(--status-commented); }
|
|
1828
|
+
.s-stale { --s: var(--status-stale); }
|
|
1829
|
+
.s-approved { --s: var(--status-approved); }
|
|
1830
|
+
.s-unreviewed { --s: var(--status-unreviewed); }
|
|
1831
|
+
.s-trusted { --s: var(--status-trusted); }
|
|
1832
|
+
.dot.ss, .card.ss .dot { background: var(--s); box-shadow: none; }
|
|
1833
|
+
.dot.ss.k-external, .card.ss.k-external .dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--s); }
|
|
1834
|
+
.cluster-card .dot { background: var(--grad); }
|
|
1835
|
+
|
|
1836
|
+
/* the guide (CollabSpec, G1): the first-visit tour, and the sheet of keys */
|
|
1837
|
+
#tour { position: fixed; inset: 0; z-index: 60; }
|
|
1838
|
+
/* the shade: four rectangles around the place lit up (a box-shadow that large is not drawn by every
|
|
1839
|
+
renderer); the ring marks the place */
|
|
1840
|
+
.tour-shade { position: fixed; left: 0; top: 0; background: rgba(12, 12, 20, 0.5); transition: all 0.3s; }
|
|
1841
|
+
.tour-spot {
|
|
1842
|
+
position: fixed; border-radius: 12px; pointer-events: none;
|
|
1843
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 75%, transparent); transition: all 0.3s;
|
|
1844
|
+
}
|
|
1845
|
+
.tour-spot.none { box-shadow: none; }
|
|
1846
|
+
.tour-card {
|
|
1847
|
+
position: fixed; left: 0; top: 0; width: min(310px, calc(100vw - 24px)); padding: 14px 16px 12px; border-radius: 14px;
|
|
1848
|
+
background: var(--surface-solid); transition: transform 0.3s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
1849
|
+
}
|
|
1850
|
+
.tour-step { font-size: 11.5px; color: var(--text-2); margin-bottom: 4px; }
|
|
1851
|
+
.tour-title { font-weight: 700; font-size: 16px; letter-spacing: -0.01em; margin-bottom: 6px; }
|
|
1852
|
+
.tour-text { font-size: 13px; line-height: 1.5; color: var(--text); }
|
|
1853
|
+
.tour-actions { display: flex; align-items: center; gap: 6px; margin-top: 14px; }
|
|
1854
|
+
.tour-gap { flex: 1; }
|
|
1855
|
+
#help { position: fixed; inset: 0; z-index: 45; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.22); }
|
|
1856
|
+
.help-box { width: min(660px, calc(100vw - 32px)); max-height: calc(100vh - 48px); overflow: auto; outline: none; }
|
|
1857
|
+
.help-head { display: flex; justify-content: space-between; align-items: center; }
|
|
1858
|
+
.help-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 24px; }
|
|
1859
|
+
@media (max-width: 640px) { .help-grid { grid-template-columns: 1fr; } }
|
|
1860
|
+
.help-h { font-size: 11.5px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
|
|
1861
|
+
.help-row { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 10px; align-items: baseline; font-size: 12.5px; padding: 3px 0; }
|
|
1862
|
+
.help-k { color: var(--text-2); line-height: 1.6; }
|
|
1863
|
+
.help-g { font-style: italic; }
|
|
1864
|
+
/* the reader's "Open in editor" template, under the keys */
|
|
1865
|
+
.help-editor, .help-about { display: flex; flex-direction: column; gap: 6px; margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); }
|
|
1866
|
+
.help-note { color: var(--text-2); font-size: 12px; line-height: 1.45; }
|
|
1867
|
+
.help-note code { font: 11px var(--mono); background: var(--code-bg); padding: 1px 4px; border-radius: 4px; overflow-wrap: anywhere; }
|
|
1868
|
+
.help-input {
|
|
1869
|
+
font: 12.5px var(--mono); color: var(--text); background: var(--surface-solid); border: 1px solid var(--line);
|
|
1870
|
+
border-radius: 8px; padding: 7px 10px;
|
|
1871
|
+
}
|
|
1872
|
+
.help-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
1873
|
+
kbd {
|
|
1874
|
+
font: 11px var(--mono); color: var(--text); padding: 1px 6px; border-radius: 5px; border: 1px solid var(--line);
|
|
1875
|
+
border-bottom-width: 2px; background: var(--surface-solid); white-space: nowrap;
|
|
1876
|
+
}
|
|
1877
|
+
.help-btn {
|
|
1878
|
+
width: 30px; height: 30px; flex: none; border-radius: 50%; border: 1px solid var(--line); background: var(--surface-solid);
|
|
1879
|
+
color: var(--text-2); font: 600 14px var(--font); cursor: pointer;
|
|
1880
|
+
}
|
|
1881
|
+
.help-btn:hover { border-color: var(--accent); color: var(--accent); }
|
|
1882
|
+
|
|
1883
|
+
/* the zoom buttons: the bottom right of the canvas, beside the panel when it is open */
|
|
1884
|
+
#zoom {
|
|
1885
|
+
position: fixed; right: calc(var(--inset-right, 0px) + 12px); bottom: 48px; z-index: 6;
|
|
1886
|
+
display: flex; flex-direction: column; padding: 3px; gap: 2px; border-radius: 12px;
|
|
1887
|
+
transition: right 0.32s cubic-bezier(0.2, 0.9, 0.25, 1);
|
|
1888
|
+
}
|
|
1889
|
+
#zoom button {
|
|
1890
|
+
display: grid; place-items: center; width: 32px; height: 30px; padding: 0; border: 0; border-radius: 9px;
|
|
1891
|
+
background: transparent; color: var(--text); cursor: pointer;
|
|
1892
|
+
}
|
|
1893
|
+
#zoom button:hover { background: var(--code-bg); color: var(--accent); }
|
|
1894
|
+
#zoom svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
1895
|
+
/* the edges drawn: on or off for this reader */
|
|
1896
|
+
/* ⋯: the eyes' less used switches, opening to the left; a dot on it while the lock is on, dashed
|
|
1897
|
+
while the drag key (⌘ on a Mac, Ctrl elsewhere) is held */
|
|
1898
|
+
#eyes-btn { position: relative; }
|
|
1899
|
+
#eyes-btn circle { fill: currentColor; stroke: none; }
|
|
1900
|
+
#eyes-btn.flag::after { content: ""; position: absolute; top: 4px; right: 5px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
|
|
1901
|
+
#eyes-btn.held { outline: 1.5px dashed color-mix(in srgb, var(--accent) 70%, transparent); outline-offset: -3px; }
|
|
1902
|
+
#eyes-pop {
|
|
1903
|
+
position: absolute; right: calc(100% + 8px); bottom: 0; display: flex; flex-direction: column; gap: 2px;
|
|
1904
|
+
padding: 4px; border-radius: 12px; min-width: 210px; box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
1905
|
+
background: color-mix(in srgb, var(--surface-solid) 94%, transparent);
|
|
1906
|
+
}
|
|
1907
|
+
#zoom #eyes-pop button.eye {
|
|
1908
|
+
display: flex; align-items: center; gap: 8px; width: 100%; height: 30px; padding: 0 8px; justify-content: flex-start;
|
|
1909
|
+
color: var(--text-2); font: 12.5px var(--font); text-align: left;
|
|
1910
|
+
}
|
|
1911
|
+
#zoom #eyes-pop button.eye.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
|
|
1912
|
+
#zoom #eyes-pop button.eye:hover { background: var(--code-bg); color: var(--text); }
|
|
1913
|
+
#zoom #eyes-pop button.eye.on:hover { color: var(--accent); }
|
|
1914
|
+
#eyes-pop button.eye circle, #eyes-pop button.eye rect { fill: currentColor; stroke: none; }
|
|
1915
|
+
#eyes-pop svg { flex: none; }
|
|
1916
|
+
.eye-l { flex: 1; }
|
|
1917
|
+
#eyes-pop kbd { font-size: 10.5px; padding: 0 5px; color: var(--text-2); }
|
|
1918
|
+
.eye-theme { display: flex; align-items: center; gap: 8px; padding: 4px 4px 2px 8px; margin-top: 2px; border-top: 1px solid var(--line); color: var(--text-2); font-size: 12.5px; }
|
|
1919
|
+
#zoom .eye-theme .seg button { width: 30px; height: 24px; padding: 0; border-radius: 6px; color: var(--text-2); background: transparent; }
|
|
1920
|
+
#zoom .eye-theme .seg button.on { color: var(--accent); background: var(--surface-solid); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); }
|
|
1921
|
+
/* the lock: shut and filled while drags only pan, open otherwise; the drag key held shows dashed */
|
|
1922
|
+
#lock-btn .lk-shackle { transition: transform 0.15s; }
|
|
1923
|
+
#lock-btn:not(.on) .lk-shackle { transform: translate(2.6px, -1px); }
|
|
1924
|
+
#lock-btn.on .lk-body { fill: currentColor; }
|
|
1925
|
+
#lock-btn.held { outline: 1.5px dashed color-mix(in srgb, var(--accent) 70%, transparent); outline-offset: -3px; }
|
|
1926
|
+
|
|
1927
|
+
/* shared changes on the canvas (web/src/notes.ts): who did what, where */
|
|
1928
|
+
#notes { position: fixed; inset: 0; pointer-events: none; z-index: 12; overflow: hidden; }
|
|
1929
|
+
.note {
|
|
1930
|
+
position: absolute; left: 0; top: 0; padding: 4px 10px; border-radius: 8px; white-space: nowrap;
|
|
1931
|
+
background: var(--surface-solid); box-shadow: inset 3px 0 0 var(--c), var(--shadow); font-size: 12px; color: var(--text);
|
|
1932
|
+
transition: opacity 0.6s;
|
|
1933
|
+
}
|
|
1934
|
+
.note b { color: var(--c); }
|
|
1935
|
+
|
|
1936
|
+
/* the notes on the board (web/src/sticky.ts): at a fixed size on the screen, under the panels. A note
|
|
1937
|
+
is a round icon at its place and, expanded, its card hanging from the icon on a thin leader (the
|
|
1938
|
+
owner's decision, 2026-10-11); the note's element is no box of its own, each part is placed on the
|
|
1939
|
+
layer by itself, so that the layer stacks them, bottom to top (shared/notecard.ts, NOTE_Z; the
|
|
1940
|
+
owner's decision, 2026-10-12): the leaders (1); the icons, dots and folded clusters' markers (2);
|
|
1941
|
+
the cards (3, those pressed or opened last above by their rank, written on each); what would hold
|
|
1942
|
+
a dragged note (68); the icon being dragged (69). An expanded card covers the icons under it */
|
|
1943
|
+
#stickies { position: fixed; inset: 0; pointer-events: none; z-index: 4; overflow: hidden; }
|
|
1944
|
+
.sticky { position: absolute; left: 0; top: 0; width: 0; height: 0; color: var(--note-text); font: 12.5px/1.45 var(--font); }
|
|
1945
|
+
.sk-icon { width: 14px; height: 14px; flex: none; color: var(--note-icon); }
|
|
1946
|
+
/* the icon, 24 px across, centred on the note's place: its ring solid in the accent for the
|
|
1947
|
+
project's notes, dashed for a view's own */
|
|
1948
|
+
.sk-ico {
|
|
1949
|
+
position: absolute; left: -12px; top: -12px; z-index: 2; box-sizing: border-box; width: 24px; height: 24px; border-radius: 50%;
|
|
1950
|
+
display: grid; place-items: center; pointer-events: auto; cursor: pointer; user-select: none; touch-action: none;
|
|
1951
|
+
background: var(--surface-solid); border: 1.5px solid var(--note-icon); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.22), 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
1952
|
+
}
|
|
1953
|
+
.sticky.vnote .sk-ico { border-style: dashed; }
|
|
1954
|
+
/* zoomed out, the icon turns into a dot the size of a declaration's point (the owner's decision,
|
|
1955
|
+
2026-10-12): web/src/sticky.ts scales the icon down (--s) and sets how much of it shows (--t); the
|
|
1956
|
+
dot, coloured by what the note carries, covers it as it goes, with a thin edge of the page's
|
|
1957
|
+
surface whatever the scale, and the pointer reaches it a little beyond its edge (--hit) */
|
|
1958
|
+
.sk-dot {
|
|
1959
|
+
position: absolute; inset: -1.5px; border-radius: 50%; pointer-events: none; opacity: calc(1 - var(--t, 1));
|
|
1960
|
+
background: var(--note-icon); box-shadow: 0 0 0 calc(1px / var(--s, 1)) var(--surface-solid);
|
|
1961
|
+
}
|
|
1962
|
+
.sticky.nk-paper .sk-dot { background: var(--note-paper); }
|
|
1963
|
+
.sticky.nk-image .sk-dot { background: var(--note-image); }
|
|
1964
|
+
.sk-ico::before { content: ""; position: absolute; inset: calc(-1 * var(--hit, 0px)); border-radius: 50%; }
|
|
1965
|
+
.sticky.shrunk .sk-ico { box-shadow: none; }
|
|
1966
|
+
.sticky.shrunk .sk-count { opacity: var(--t, 1); }
|
|
1967
|
+
.sticky.shrunk .sk-ico:hover .sk-dot { box-shadow: 0 0 0 calc(1px / var(--s, 1)) var(--surface-solid), 0 0 0 calc(3px / var(--s, 1)) color-mix(in srgb, var(--note-icon) 45%, transparent); }
|
|
1968
|
+
/* attached to a declaration (the owner's decisions, 2026-10-12): a thin dashed leader from the icon
|
|
1969
|
+
toward the declaration's point, ending in a small diamond on the point's rim, in the note accent;
|
|
1970
|
+
web/src/sticky.ts scales the line's width and the diamond as the icon turns into its dot */
|
|
1971
|
+
.sk-dlead {
|
|
1972
|
+
position: absolute; left: 0; top: 0; z-index: 1; height: 0; transform-origin: 0 0; pointer-events: none;
|
|
1973
|
+
border-top: 1.5px dashed color-mix(in srgb, var(--note-icon) 85%, transparent);
|
|
1974
|
+
}
|
|
1975
|
+
.sk-dmark {
|
|
1976
|
+
position: absolute; left: -2.5px; top: -2.5px; z-index: 1; width: 5px; height: 5px; pointer-events: none;
|
|
1977
|
+
background: var(--note-icon); box-shadow: 0 0 0 1px var(--surface-solid);
|
|
1978
|
+
}
|
|
1979
|
+
.sticky:not(.attached) .sk-dlead, .sticky:not(.attached) .sk-dmark { display: none; }
|
|
1980
|
+
/* the pointer's target, over the declarations under it */
|
|
1981
|
+
.sk-ico:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--note-icon) 24%, transparent), 0 1px 2px rgba(0, 0, 0, 0.22); }
|
|
1982
|
+
/* expanded, its card hidden by the zoom: a click on the icon brings it near enough to read */
|
|
1983
|
+
.sticky.auto .sk-ico { background: color-mix(in srgb, var(--note-icon) 18%, var(--surface-solid)); }
|
|
1984
|
+
/* a note that carries more than one thing: how many, on its icon's lower right */
|
|
1985
|
+
.sk-count {
|
|
1986
|
+
position: absolute; right: -6px; bottom: -6px; box-sizing: border-box; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 7px;
|
|
1987
|
+
display: grid; place-items: center; font: 700 9px/1 var(--font); font-variant-numeric: tabular-nums; color: var(--note-icon);
|
|
1988
|
+
background: var(--surface-solid); box-shadow: 0 0 0 1px var(--note-icon);
|
|
1989
|
+
}
|
|
1990
|
+
.sk-lead {
|
|
1991
|
+
position: absolute; left: 0; top: 0; z-index: 1; height: 0; transform-origin: 0 0; pointer-events: none;
|
|
1992
|
+
border-top: 1.2px solid color-mix(in srgb, var(--note-icon) 75%, transparent);
|
|
1993
|
+
}
|
|
1994
|
+
.sticky.vnote .sk-lead { border-top-style: dashed; }
|
|
1995
|
+
.sk-card {
|
|
1996
|
+
position: absolute; left: 0; top: 0; z-index: 3; pointer-events: auto; user-select: none; touch-action: none; cursor: default;
|
|
1997
|
+
width: max-content; max-width: 260px; padding: 7px 10px 6px 12px; border-radius: 8px;
|
|
1998
|
+
background: var(--note-bg); box-shadow: inset 2px 0 0 var(--note-icon), 0 0 0 1px var(--note-edge), var(--shadow);
|
|
1999
|
+
}
|
|
2000
|
+
.sticky:not(.open) .sk-card, .sticky:not(.open) .sk-lead { display: none; }
|
|
2001
|
+
/* a long text scrolls in the card (the owner's decision of 2026-10-12): the wheel, a trackpad's two
|
|
2002
|
+
fingers (web/src/sticky.ts, wheelGoes), its scrollbar and, where it is longer than the card shows,
|
|
2003
|
+
a finger; its ends never pass the scroll on */
|
|
2004
|
+
.sk-text { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 260px; overflow: auto; overscroll-behavior: contain; }
|
|
2005
|
+
.sk-text.scrolls { touch-action: pan-y; }
|
|
2006
|
+
.sk-text code { font: 11.5px var(--mono); background: var(--code-bg); padding: 0 3px; border-radius: 4px; }
|
|
2007
|
+
.sk-text .tk-pre { margin: 4px 0; white-space: pre-wrap; font: 11.5px var(--mono); }
|
|
2008
|
+
.sk-text .tk-decl { color: var(--accent); cursor: pointer; }
|
|
2009
|
+
.sk-by { margin-top: 4px; font-size: 11px; color: var(--note-mute); display: flex; align-items: center; gap: 3px; }
|
|
2010
|
+
/* what a note carries (AttachmentSpec decision 12): under its text, at the card's width — 320 px
|
|
2011
|
+
where it carries an image or a clip, 260 px where it carries whole papers alone (sticky.ts,
|
|
2012
|
+
CARRY_W); each drawing as large as it is drawn and no larger, its shape kept, never stretched */
|
|
2013
|
+
.sticky.carrying .sk-card { width: 260px; max-width: none; }
|
|
2014
|
+
.sticky.carrying.pictured .sk-card { width: 320px; }
|
|
2015
|
+
.sk-carries { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
|
|
2016
|
+
.sk-att {
|
|
2017
|
+
position: relative; display: block; width: 100%; padding: 0; border: 0; border-radius: 6px; overflow: hidden; cursor: zoom-in;
|
|
2018
|
+
background: var(--canvas); box-shadow: 0 0 0 1px var(--note-edge); color: inherit; font: inherit; text-align: left;
|
|
2019
|
+
}
|
|
2020
|
+
.sk-att:hover { box-shadow: 0 0 0 1.5px var(--note-icon); }
|
|
2021
|
+
.sk-att-pic { display: block; max-width: 100%; max-height: 240px; width: auto; height: auto; margin: 0 auto; background: #fff; }
|
|
2022
|
+
.sk-att-clip .sk-att-pic { max-height: 260px; }
|
|
2023
|
+
.sk-att-cap { display: block; padding: 2px 7px 3px; font-size: 11px; color: var(--note-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-top: 1px solid var(--note-edge); }
|
|
2024
|
+
.sk-att-pdf { display: flex; align-items: flex-start; gap: 8px; padding: 5px; }
|
|
2025
|
+
.sk-att-page { flex: none; width: 64px; height: auto; max-height: 96px; object-fit: contain; object-position: top; background: #fff; box-shadow: 0 0 0 1px var(--note-edge); border-radius: 2px; }
|
|
2026
|
+
.sk-att-t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
2027
|
+
.sk-att-title { font-weight: 600; font-size: 12px; line-height: 1.3; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
|
|
2028
|
+
.sk-att-meta { font-size: 11px; color: var(--note-mute); }
|
|
2029
|
+
.sk-att.arch { opacity: 0.72; }
|
|
2030
|
+
.sk-att-arch { position: absolute; top: 4px; right: 4px; padding: 0 6px; border-radius: 6px; font-size: 10.5px; background: var(--surface-solid); color: var(--banner-warn); box-shadow: 0 0 0 1px var(--note-edge); }
|
|
2031
|
+
.sk-att-pdf .sk-att-arch { position: static; align-self: flex-start; }
|
|
2032
|
+
.sk-att-none, .sk-att-why { display: block; padding: 6px 8px; font-size: 11.5px; color: var(--note-mute); cursor: default; white-space: normal; }
|
|
2033
|
+
.sk-att-none code { font: 11px var(--mono); }
|
|
2034
|
+
.sk-att.failed { cursor: default; }
|
|
2035
|
+
/* moved: the icon with its card, the icon over everything so that it stays in sight; or the card
|
|
2036
|
+
alone on its leader */
|
|
2037
|
+
.sticky.moving .sk-ico { z-index: 69; cursor: grabbing; box-shadow: 0 0 0 4px color-mix(in srgb, var(--note-icon) 24%, transparent), var(--shadow-lg); }
|
|
2038
|
+
.sticky.moving .sk-card { opacity: 0.88; }
|
|
2039
|
+
.sticky.hanging .sk-card { cursor: grabbing; box-shadow: inset 2px 0 0 var(--note-icon), 0 0 0 1px var(--note-edge), var(--shadow-lg); }
|
|
2040
|
+
.sticky.fresh .sk-ico, .sticky.fresh .sk-card { animation: sk-fresh 1.4s ease-out; }
|
|
2041
|
+
@keyframes sk-fresh { 0%, 30% { box-shadow: 0 0 0 1px var(--note-edge), 0 0 0 5px color-mix(in srgb, var(--note-icon) 45%, transparent), var(--shadow); } }
|
|
2042
|
+
/* a view's own note (AttachmentSpec decision 14): drawn apart from the project's, a dashed ring and
|
|
2043
|
+
edge in the accent colour, and the view's mark, a tab, under its text */
|
|
2044
|
+
.sticky.vnote .sk-card { box-shadow: var(--shadow); outline: 1.2px dashed color-mix(in srgb, var(--note-icon) 75%, transparent); outline-offset: -1.2px; border-radius: 10px; }
|
|
2045
|
+
.sticky.vnote.hanging .sk-card { box-shadow: var(--shadow-lg); }
|
|
2046
|
+
.sk-view { width: 12px; height: 12px; flex: none; color: var(--note-icon); }
|
|
2047
|
+
.sk-whose { margin-top: 2px; font-size: 11px; color: var(--note-mute); display: flex; align-items: center; gap: 3px; }
|
|
2048
|
+
/* a note on the ring around the board (decision 16): what it is about is lit while the pointer is on
|
|
2049
|
+
it, on this layer under the notes */
|
|
2050
|
+
.sticky.ring:hover .sk-card { box-shadow: 0 0 0 1px var(--note-icon), var(--shadow); }
|
|
2051
|
+
.sticky.vnote.ring:hover .sk-card { box-shadow: var(--shadow); }
|
|
2052
|
+
/* what would hold a dragged note, over the cards so that a declaration or a circle under one still
|
|
2053
|
+
shows, under the icon dragged */
|
|
2054
|
+
.sticky-halo { position: absolute; inset: 0; z-index: 68; width: 100%; height: 100%; pointer-events: none; }
|
|
2055
|
+
/* a folded cluster that holds notes: how many, on its disc, among the icons, under the cards */
|
|
2056
|
+
.sticky-mark {
|
|
2057
|
+
position: absolute; left: 0; top: 0; z-index: 2; pointer-events: auto; display: flex; align-items: center; gap: 2px; height: 20px; padding: 0 6px 0 3px;
|
|
2058
|
+
border: 0; border-radius: 10px; background: var(--note-bg); color: var(--note-text); font: 600 11px var(--font);
|
|
2059
|
+
box-shadow: 0 0 0 1px var(--note-edge), var(--shadow);
|
|
2060
|
+
}
|
|
2061
|
+
.sticky-mark .sk-icon { width: 13px; height: 13px; }
|
|
2062
|
+
/* writing or editing a note */
|
|
2063
|
+
.sticky-editor {
|
|
2064
|
+
/* above the floating windows and the popovers, below the canvas's menu: a note is written from the
|
|
2065
|
+
paper's window too */
|
|
2066
|
+
position: fixed; left: 0; top: 0; pointer-events: auto; display: flex; flex-direction: column; gap: 6px; width: 300px; padding: 8px 10px 8px;
|
|
2067
|
+
border-radius: 10px; background: var(--note-bg); color: var(--note-text); box-shadow: 0 0 0 1px var(--note-edge), var(--shadow-lg); z-index: 37;
|
|
2068
|
+
}
|
|
2069
|
+
.sk-ed-h { display: flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; color: var(--note-mute); }
|
|
2070
|
+
.sticky-editor textarea {
|
|
2071
|
+
resize: vertical; min-height: 90px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--canvas); color: var(--text); font: 12.5px/1.45 var(--font);
|
|
2072
|
+
}
|
|
2073
|
+
.sticky-editor textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
2074
|
+
.sk-ed-err { color: var(--bad); font-size: 11.5px; }
|
|
2075
|
+
.sk-ed-f { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; }
|
|
2076
|
+
.sk-ed-f .muted { color: var(--note-mute); }
|
|
2077
|
+
|
|
2078
|
+
/* the canvas's menu (web/src/ctxmenu.ts): what can be done with what it was opened on, over
|
|
2079
|
+
everything but the modal windows, a submenu beside it */
|
|
2080
|
+
#ctxmenu {
|
|
2081
|
+
position: fixed; z-index: 38; min-width: 210px; max-width: min(320px, calc(100vw - 16px)); padding: 4px; border-radius: 12px;
|
|
2082
|
+
background: color-mix(in srgb, var(--surface-solid) 94%, transparent); box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
2083
|
+
font-size: 12.5px; outline: none;
|
|
2084
|
+
}
|
|
2085
|
+
.cm-h {
|
|
2086
|
+
padding: 4px 8px 5px; font-size: 11px; font-weight: 600; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
2087
|
+
}
|
|
2088
|
+
.cm-item {
|
|
2089
|
+
display: flex; align-items: center; gap: 12px; width: 100%; height: 28px; padding: 0 8px; border: 0; border-radius: 7px;
|
|
2090
|
+
background: transparent; color: var(--text); font: 12.5px var(--font); text-align: left;
|
|
2091
|
+
}
|
|
2092
|
+
.cm-item:hover:not(:disabled), .cm-item:focus-visible, .cm-item:focus:not(:disabled), .cm-item[aria-expanded="true"] { background: var(--code-bg); color: var(--accent); outline: none; }
|
|
2093
|
+
.cm-item:disabled { color: var(--text-3); cursor: default; }
|
|
2094
|
+
.cm-l { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2095
|
+
.cm-key { font: 10.5px var(--mono); color: var(--text-3); }
|
|
2096
|
+
.cm-note { font-size: 11px; color: var(--text-3); }
|
|
2097
|
+
.cm-more { color: var(--text-3); font-size: 10px; }
|
|
2098
|
+
.cm-sep { height: 1px; margin: 3px 6px; background: var(--line); }
|
|
2099
|
+
.cm-sub {
|
|
2100
|
+
position: absolute; min-width: 190px; max-width: 300px; max-height: calc(100vh - 16px); overflow: auto; padding: 4px; border-radius: 12px;
|
|
2101
|
+
background: color-mix(in srgb, var(--surface-solid) 96%, transparent); box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
2102
|
+
}
|
|
2103
|
+
.cm-ask { display: flex; flex-direction: column; gap: 8px; padding: 4px 6px 6px; width: 260px; }
|
|
2104
|
+
.zoom-sep { height: 1px; margin: 2px 5px; background: var(--line); }
|
|
2105
|
+
|
|
2106
|
+
/* ---------------------------------------------------------------- footer, tooltip, loader */
|
|
2107
|
+
|
|
2108
|
+
/* the legend (web/src/legend.ts): at the bottom left of the canvas, beside the side panel; folded to
|
|
2109
|
+
a chip, open to a card that grows upwards */
|
|
2110
|
+
#foot {
|
|
2111
|
+
position: fixed; left: 284px; bottom: 12px; z-index: 6; display: flex; align-items: flex-end;
|
|
2112
|
+
color: var(--text-2); font-size: 11.5px; pointer-events: none;
|
|
2113
|
+
}
|
|
2114
|
+
#legend { pointer-events: auto; }
|
|
2115
|
+
.lg-chip {
|
|
2116
|
+
display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 8px 0 9px; border-radius: 999px;
|
|
2117
|
+
border: 0.5px solid var(--line); background: var(--surface); color: var(--text);
|
|
2118
|
+
backdrop-filter: saturate(180%) blur(16px); -webkit-backdrop-filter: saturate(180%) blur(16px);
|
|
2119
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06); font: 500 12px var(--font); white-space: nowrap;
|
|
2120
|
+
}
|
|
2121
|
+
.lg-chip:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
|
|
2122
|
+
/* the scheme's swatch: the kinds' colours round a dot, or a pie of the board's review */
|
|
2123
|
+
.lg-swatch { width: 10px; height: 10px; border-radius: 50%; flex: none; }
|
|
2124
|
+
.lg-swatch.lg-kind {
|
|
2125
|
+
background: conic-gradient(var(--k-def) 0 20%, var(--k-structure) 0 40%, var(--k-instance) 0 60%, var(--k-theorem) 0 80%, var(--k-axiom) 0);
|
|
2126
|
+
}
|
|
2127
|
+
.lg-chip-n { color: var(--text-2); font-variant-numeric: tabular-nums; font-size: 11.5px; }
|
|
2128
|
+
.lg-chev { color: var(--text-3); font-size: 10px; }
|
|
2129
|
+
.lg-card {
|
|
2130
|
+
display: flex; flex-direction: column; gap: 6px; width: 228px; padding: 8px 10px 9px; border-radius: 14px;
|
|
2131
|
+
background: var(--surface); backdrop-filter: saturate(180%) blur(22px); -webkit-backdrop-filter: saturate(180%) blur(22px);
|
|
2132
|
+
border: 0.5px solid var(--line); box-shadow: var(--shadow);
|
|
2133
|
+
}
|
|
2134
|
+
.lg-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
2135
|
+
.lg-x { border: 0; background: transparent; color: var(--text-3); width: 22px; height: 22px; border-radius: 6px; font-size: 10px; }
|
|
2136
|
+
.lg-x:hover { background: var(--code-bg); color: var(--text); }
|
|
2137
|
+
.lg-rows { display: flex; flex-direction: column; gap: 1px; }
|
|
2138
|
+
.lg-row { display: grid; grid-template-columns: 10px minmax(0, 1fr) auto; align-items: center; gap: 7px; padding: 1px 2px; color: var(--text); font-size: 12px; }
|
|
2139
|
+
.lg-row .dot { width: 9px; height: 9px; }
|
|
2140
|
+
.lg-row.none { color: var(--text-3); }
|
|
2141
|
+
.lg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2142
|
+
.lg-n { color: var(--text-2); font-variant-numeric: tabular-nums; font-size: 11.5px; }
|
|
2143
|
+
.lg-row.none .lg-n { color: var(--text-3); }
|
|
2144
|
+
/* by status, the board's progress, in the scheme's own colours */
|
|
2145
|
+
.lg-prog { display: flex; flex-direction: column; gap: 3px; color: var(--text-2); font-size: 11.5px; }
|
|
2146
|
+
.lg-prog .rv-bar i.ok { background: var(--status-approved); }
|
|
2147
|
+
.lg-prog .rv-bar i.commented { background: var(--status-commented); }
|
|
2148
|
+
.lg-prog .rv-bar i.stale { background: var(--status-stale); }
|
|
2149
|
+
.lg-edge { display: flex; align-items: center; gap: 6px; padding-top: 5px; border-top: 1px solid var(--line); color: var(--text-2); }
|
|
2150
|
+
.edge-key { width: 26px; height: 3px; border-radius: 2px; background: linear-gradient(90deg, var(--edge-from), var(--edge-to)); }
|
|
2151
|
+
/* the key graph's edges under Keys: dashed, as the canvas draws them */
|
|
2152
|
+
.edge-key.dashed {
|
|
2153
|
+
-webkit-mask: repeating-linear-gradient(90deg, #000 0 6px, transparent 6px 10px); mask: repeating-linear-gradient(90deg, #000 0 6px, transparent 6px 10px);
|
|
2154
|
+
}
|
|
2155
|
+
.lg-edge + .lg-edge { border-top: 0; padding-top: 2px; }
|
|
2156
|
+
.lg-keys { flex-direction: column; align-items: flex-start; gap: 1px; }
|
|
2157
|
+
.lg-keys-l { display: flex; align-items: center; gap: 6px; }
|
|
2158
|
+
.lg-keys-n { color: var(--text-3); font-size: 11px; }
|
|
2159
|
+
|
|
2160
|
+
.tip {
|
|
2161
|
+
position: fixed; left: 0; top: 0; z-index: 20; pointer-events: none; display: flex; align-items: center; gap: 6px;
|
|
2162
|
+
background: var(--surface-solid); border-radius: 8px; padding: 4px 9px; box-shadow: var(--shadow);
|
|
2163
|
+
font: 11.5px var(--mono); max-width: 520px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
.meter {
|
|
2167
|
+
position: fixed; right: 12px; top: 108px; z-index: 20; font: 11px var(--mono); color: var(--text-2);
|
|
2168
|
+
background: var(--surface); border-radius: 8px; padding: 4px 8px; pointer-events: none;
|
|
2169
|
+
}
|
|
2170
|
+
.tk-keyword { color: var(--tk-keyword); font-weight: 600; }
|
|
2171
|
+
.tk-type { color: var(--tk-type); }
|
|
2172
|
+
.tk-comment, .tk-doc { color: var(--tk-comment); font-style: italic; }
|
|
2173
|
+
.tk-string { color: var(--tk-string); }
|
|
2174
|
+
.tk-number { color: var(--tk-number); }
|
|
2175
|
+
.tk-attr { color: var(--tk-attr); }
|
|
2176
|
+
.tk-op { color: var(--tk-op); }
|
|
2177
|
+
.tk-sorry { color: #fff; background: #ff375f; border-radius: 3px; padding: 0 2px; }
|
|
2178
|
+
|
|
2179
|
+
#loader {
|
|
2180
|
+
position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; background: var(--canvas);
|
|
2181
|
+
transition: opacity 0.4s;
|
|
2182
|
+
}
|
|
2183
|
+
#loader.gone { opacity: 0; pointer-events: none; }
|
|
2184
|
+
.loader-box { text-align: center; max-width: 640px; padding: 16px; }
|
|
2185
|
+
.logo.big { font-size: 40px; display: inline-block; margin-bottom: 8px; }
|
|
2186
|
+
#loader-title { color: var(--text-2); margin-bottom: 14px; }
|
|
2187
|
+
#loader-log { text-align: left; color: var(--text-3); font: 11px/1.5 var(--mono); white-space: pre-wrap; min-height: 9em; }
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
@media (max-width: 900px) {
|
|
2191
|
+
#side { display: none; }
|
|
2192
|
+
.light-l { display: none; }
|
|
2193
|
+
#lightup button { padding: 5px 8px; }
|
|
2194
|
+
#lightup .steps button { padding: 2px 6px; }
|
|
2195
|
+
#panel { width: auto; left: 12px; }
|
|
2196
|
+
#foot { left: 12px; }
|
|
2197
|
+
.seg button { padding: 5px 8px; }
|
|
2198
|
+
#search { width: 140px; }
|
|
2199
|
+
.brand .project { display: none; }
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
/* ---------------------------------------------------------------- the Time Machine */
|
|
2203
|
+
|
|
2204
|
+
/* its bar takes the tabs' place while it is open (HistorySpec decision 16) */
|
|
2205
|
+
body.tm #tabs, body.tm .views-wrap, body.tm .vb-gap, body.tm .light-l { display: none; }
|
|
2206
|
+
#tmbar {
|
|
2207
|
+
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 10px; height: 36px;
|
|
2208
|
+
padding: 0 4px 0 10px; border-radius: 12px; overflow: hidden;
|
|
2209
|
+
}
|
|
2210
|
+
.tm-icon, .tab-clock, #tm-kept > svg { display: inline-grid; place-items: center; flex: none; color: var(--accent); }
|
|
2211
|
+
.tm-icon svg, .tab-clock svg, #tm-kept > svg { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
|
|
2212
|
+
.tab-clock { margin-right: -1px; }
|
|
2213
|
+
.vm-name .tab-clock { margin-right: 4px; vertical-align: -1px; }
|
|
2214
|
+
.tm-view { flex: none; max-width: 130px; font-weight: 600; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2215
|
+
.tm-line { flex: none; cursor: pointer; touch-action: none; border-radius: 6px; }
|
|
2216
|
+
.tm-line:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 50%, transparent); outline-offset: 1px; }
|
|
2217
|
+
.tm-line svg { display: block; }
|
|
2218
|
+
/* a ruler whose builds do not all fit scrolls: its ends fade where there are builds beyond them */
|
|
2219
|
+
.tm-line.more-l { -webkit-mask-image: linear-gradient(to right, transparent, #000 12px); mask-image: linear-gradient(to right, transparent, #000 12px); }
|
|
2220
|
+
.tm-line.more-r { -webkit-mask-image: linear-gradient(to left, transparent, #000 12px); mask-image: linear-gradient(to left, transparent, #000 12px); }
|
|
2221
|
+
.tm-line.more-l.more-r { -webkit-mask-image: linear-gradient(to right, transparent, #000 12px, #000 calc(100% - 12px), transparent); mask-image: linear-gradient(to right, transparent, #000 12px, #000 calc(100% - 12px), transparent); }
|
|
2222
|
+
.tm-axis { stroke: var(--text-3); stroke-width: 1.2; opacity: 0.7; }
|
|
2223
|
+
/* a tick per build, a step apart (the owner's decision of 2026-10-10): long for the first build of a
|
|
2224
|
+
commit, short for the same commit built again */
|
|
2225
|
+
.tm-tick { stroke: var(--text-2); stroke-width: 1.3; stroke-linecap: round; }
|
|
2226
|
+
.tm-tick.major { stroke-width: 1.7; }
|
|
2227
|
+
.tm-tick.on { stroke: var(--accent); stroke-width: 2.6; }
|
|
2228
|
+
/* a build whose time only its extraction says: hollow */
|
|
2229
|
+
.tm-tick.approx { stroke-dasharray: 2 2; }
|
|
2230
|
+
.tm-tick-o { fill: var(--surface-solid); stroke: var(--text-2); stroke-width: 1.2; }
|
|
2231
|
+
.tm-mark { fill: var(--accent); }
|
|
2232
|
+
/* what each build is, under the pointer: an invisible step around its tick */
|
|
2233
|
+
.tm-hit { fill: transparent; }
|
|
2234
|
+
/* the build aimed at while it loads, the board showing the strong tick meanwhile: once it has been
|
|
2235
|
+
loading a moment (#tmbar.busy; a quick one never blinks), its tick tall and dashed, the handle
|
|
2236
|
+
hollow, a ring turning on it, a spinner by its time. The turns keep their phase across redraws. */
|
|
2237
|
+
.tm-busy { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; stroke-dasharray: 9 22.4; transform-box: fill-box; transform-origin: center; visibility: hidden; }
|
|
2238
|
+
#tmbar.busy .tm-busy { visibility: visible; animation: tm-spin 900ms linear infinite; }
|
|
2239
|
+
#tmbar.busy .tm-tick.aim { stroke: var(--accent); stroke-width: 1.8; stroke-dasharray: 3 2; }
|
|
2240
|
+
#tmbar.busy .tm-mark.aim { fill: var(--surface-solid); stroke: var(--accent); stroke-width: 1.4; }
|
|
2241
|
+
.tm-wait:not(.tm-failed) { display: none; }
|
|
2242
|
+
#tmbar.busy .tm-wait { display: inline; }
|
|
2243
|
+
.tm-wait.tm-failed { color: var(--tm-gone); font-style: normal; }
|
|
2244
|
+
.tm-spin { display: inline-block; width: 9px; height: 9px; margin-right: 4px; vertical-align: -1px; box-sizing: border-box; border: 1.5px solid color-mix(in srgb, var(--accent) 28%, transparent); border-top-color: var(--accent); border-radius: 50%; animation: tm-spin 900ms linear infinite; }
|
|
2245
|
+
@keyframes tm-spin { to { transform: rotate(360deg); } }
|
|
2246
|
+
@media (prefers-reduced-motion: reduce) { #tmbar.busy .tm-busy, .tm-spin { animation: none; } }
|
|
2247
|
+
.tm-when { flex: none; font-size: 12px; white-space: nowrap; color: var(--text); }
|
|
2248
|
+
.tm-when .mono { font: 11.5px var(--mono); color: var(--text-2); }
|
|
2249
|
+
.tm-latest { font-size: 10.5px; padding: 1px 6px; border-radius: 6px; background: var(--code-bg); color: var(--text-2); }
|
|
2250
|
+
.tm-wait { color: var(--text-3); font-style: italic; }
|
|
2251
|
+
.tm-sum { flex: 0 1 auto; display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; font-size: 12px; white-space: nowrap; }
|
|
2252
|
+
.tm-n {
|
|
2253
|
+
flex: none; display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 8px; border-radius: 8px;
|
|
2254
|
+
border: 1px solid var(--line); background: var(--surface-solid); color: var(--text); font: 500 11.5px var(--font); white-space: nowrap;
|
|
2255
|
+
}
|
|
2256
|
+
.tm-w { color: var(--text-2); }
|
|
2257
|
+
.tm-n:hover:not(:disabled), .tm-n.on { border-color: color-mix(in srgb, var(--accent) 60%, var(--line)); color: var(--accent); }
|
|
2258
|
+
.tm-n.none { color: var(--text-3); cursor: default; }
|
|
2259
|
+
.tm-n i { flex: none; width: 8px; height: 8px; border-radius: 50%; box-sizing: border-box; }
|
|
2260
|
+
.tm-added i { border: 1.5px solid var(--tm-new); background: color-mix(in srgb, var(--tm-new) 18%, transparent); }
|
|
2261
|
+
.tm-removed i { border: 1.5px solid var(--tm-gone); background: color-mix(in srgb, var(--tm-gone) 25%, transparent); }
|
|
2262
|
+
.tm-changed i { background: var(--text-3); box-shadow: 0 0 0 1.5px var(--surface-solid), 0 0 0 3px var(--tm-changed); width: 6px; height: 6px; margin: 0 1px; }
|
|
2263
|
+
.tm-renamed i { background: var(--text-3); box-shadow: 0 0 0 1.5px var(--surface-solid), 0 0 0 3px var(--tm-renamed); width: 6px; height: 6px; margin: 0 1px; }
|
|
2264
|
+
.tm-growth { flex: none; }
|
|
2265
|
+
.tm-growth svg { display: block; }
|
|
2266
|
+
.tm-growth-l { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-linejoin: round; opacity: 0.75; }
|
|
2267
|
+
.tm-growth-d { fill: var(--accent); stroke: var(--surface-solid); stroke-width: 1.2; }
|
|
2268
|
+
.tm-acts { flex: none; display: flex; gap: 4px; margin-left: auto; }
|
|
2269
|
+
.tm-btn {
|
|
2270
|
+
height: 26px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface-solid);
|
|
2271
|
+
color: var(--text); font: 500 12px var(--font); white-space: nowrap;
|
|
2272
|
+
}
|
|
2273
|
+
.tm-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
|
|
2274
|
+
.tm-btn:disabled { color: var(--text-3); cursor: default; }
|
|
2275
|
+
.tm-x { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: 8px; background: transparent; color: var(--text-2); font-size: 14px; }
|
|
2276
|
+
.tm-x:hover { background: var(--code-bg); color: var(--text); }
|
|
2277
|
+
/* the lists the counts open */
|
|
2278
|
+
#tm-list {
|
|
2279
|
+
position: fixed; z-index: 36; max-height: min(60vh, 520px); overflow: auto; border-radius: 14px; padding: 8px;
|
|
2280
|
+
background: color-mix(in srgb, var(--surface-solid) 94%, transparent); box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
2281
|
+
}
|
|
2282
|
+
.tm-list-h { display: flex; align-items: center; gap: 6px; padding: 2px 4px 6px; font-size: 12.5px; }
|
|
2283
|
+
.tm-list-h .icon { margin-left: auto; flex: none; }
|
|
2284
|
+
.tm-row {
|
|
2285
|
+
display: block; width: 100%; text-align: left; border: 0; background: transparent; padding: 3px 6px; border-radius: 6px;
|
|
2286
|
+
font-size: 11.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
2287
|
+
}
|
|
2288
|
+
button.tm-row:hover { background: var(--code-bg); }
|
|
2289
|
+
/* what was added since: a name, not a place on this build's board */
|
|
2290
|
+
span.tm-row { color: var(--text-2); cursor: default; }
|
|
2291
|
+
.tm-more { padding: 6px; font-size: 11.5px; }
|
|
2292
|
+
/* a view kept at a past build (HistorySpec decision 19): said where the review strip goes */
|
|
2293
|
+
#tm-kept {
|
|
2294
|
+
position: fixed; top: 110px; left: calc((100vw + var(--inset-left, 0px) - var(--inset-right, 0px)) / 2); transform: translateX(-50%); z-index: 15;
|
|
2295
|
+
display: flex; align-items: center; gap: 8px; padding: 5px 6px 5px 12px; border-radius: 12px; font-size: 12.5px;
|
|
2296
|
+
max-width: calc(100vw - var(--inset-left, 0px) - var(--inset-right, 0px) - 16px); white-space: nowrap;
|
|
2297
|
+
}
|
|
2298
|
+
#tm-kept > span { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
2299
|
+
#tm-kept .mono { font: 11.5px var(--mono); color: var(--text-2); }
|
|
2300
|
+
/* the build a past board shows, in the panel and in a source window showing its text */
|
|
2301
|
+
.banner.tm-then, .banner.sw-then { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--text); }
|
|
2302
|
+
.tm-then-m { margin-top: 4px; color: var(--text-2); }
|
|
2303
|
+
.banner.tm-then code { overflow-wrap: anywhere; }
|
|
2304
|
+
.tip-st.tip-tm { color: var(--accent); }
|
|
2305
|
+
.card-tm { margin-top: 1px; font-size: 10.5px; color: var(--text-2); white-space: nowrap; }
|
|
2306
|
+
.card.gone .card-name { text-decoration: line-through; text-decoration-color: var(--tm-gone); }
|
|
2307
|
+
/* short of room, the signed counts say what they are by their sign, and the others keep their word */
|
|
2308
|
+
@media (max-width: 1750px) { .tm-w.signed { display: none; } }
|
|
2309
|
+
@media (max-width: 1500px) { .tm-when .mono { display: none; } }
|
|
2310
|
+
@media (max-width: 1350px) { .tm-growth, .tm-w { display: none; } }
|
|
2311
|
+
@media (max-width: 1150px) { .tm-view { display: none; } .tm-n { padding: 0 6px; } }
|
|
2312
|
+
@media (max-width: 900px) { .tm-btn[data-tm-save] { display: none; } }
|