@issuegraph/viewer 0.2.0 → 0.5.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/README.md +39 -2
- package/dist/document.d.ts +286 -3
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +247 -1
- package/dist/document.js.map +1 -1
- package/dist/element.d.ts +11 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -4
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +51 -50
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +364 -168
- package/dist/layout.js.map +1 -1
- package/dist/mount.d.ts +13 -0
- package/dist/mount.d.ts.map +1 -1
- package/dist/mount.js +94 -3
- package/dist/mount.js.map +1 -1
- package/dist/navigation.d.ts +14 -0
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +20 -0
- package/dist/navigation.js.map +1 -1
- package/dist/parts.d.ts +338 -1
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +899 -30
- package/dist/parts.js.map +1 -1
- package/dist/projections/graph.d.ts +10 -0
- package/dist/projections/graph.d.ts.map +1 -1
- package/dist/projections/graph.js +413 -311
- package/dist/projections/graph.js.map +1 -1
- package/dist/projections/linear.d.ts +90 -0
- package/dist/projections/linear.d.ts.map +1 -1
- package/dist/projections/linear.js +220 -28
- package/dist/projections/linear.js.map +1 -1
- package/dist/projections/tree.d.ts.map +1 -1
- package/dist/projections/tree.js +29 -3
- package/dist/projections/tree.js.map +1 -1
- package/dist/styles.d.ts +10 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +825 -68
- package/dist/styles.js.map +1 -1
- package/dist/theme.d.ts +41 -10
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +265 -11
- package/dist/theme.js.map +1 -1
- package/dist/vocabulary.d.ts +39 -0
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +27 -0
- package/dist/vocabulary.js.map +1 -1
- package/package.json +2 -2
package/dist/styles.js
CHANGED
|
@@ -12,14 +12,26 @@
|
|
|
12
12
|
* loaded by a bare Node runtime (`ERR_UNKNOWN_FILE_EXTENSION`), and this
|
|
13
13
|
* package's floor is checked by a smoke test that imports the built entry. A
|
|
14
14
|
* string also means no consumer needs a bundler to use it.
|
|
15
|
+
*
|
|
16
|
+
* THE VIEWER DRAWS THE PANEL, and that is a decision this file records rather
|
|
17
|
+
* than a detail. §16a is one bordered surface with a header bar, hairline-
|
|
18
|
+
* separated rows and a footer group on a second ground; §9097's done-when read
|
|
19
|
+
* "§16 IS that test — the viewer with no editor attached", so the thing a host
|
|
20
|
+
* mounts with no chrome of its own has to BE the frame. Rows therefore carry no
|
|
21
|
+
* border and no radius of their own — they are separated by the panel's own
|
|
22
|
+
* hairlines — and a host that wants the panel suppressed overrides the four
|
|
23
|
+
* properties on `.ig-viewer`.
|
|
15
24
|
*/
|
|
16
25
|
export const viewerStylesheet = `
|
|
17
26
|
.ig-viewer {
|
|
18
27
|
background: var(--ig-bg);
|
|
28
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
29
|
+
border-radius: var(--ig-radius-large);
|
|
19
30
|
color: var(--ig-text-body);
|
|
20
31
|
font-family: var(--ig-font-ui);
|
|
21
32
|
font-size: var(--ig-font-size);
|
|
22
33
|
line-height: var(--ig-line-height);
|
|
34
|
+
overflow: hidden;
|
|
23
35
|
position: relative;
|
|
24
36
|
}
|
|
25
37
|
|
|
@@ -31,7 +43,7 @@ export const viewerStylesheet = `
|
|
|
31
43
|
|
|
32
44
|
.ig-viewer :focus-visible {
|
|
33
45
|
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
34
|
-
outline-offset: var(--ig-
|
|
46
|
+
outline-offset: calc(var(--ig-focus-ring) * -1);
|
|
35
47
|
}
|
|
36
48
|
|
|
37
49
|
.ig-list {
|
|
@@ -40,28 +52,366 @@ export const viewerStylesheet = `
|
|
|
40
52
|
padding: 0;
|
|
41
53
|
}
|
|
42
54
|
|
|
43
|
-
/* ── the
|
|
55
|
+
/* ── the panel header ──────────────────────────────────────────────────── */
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
/* Present only when the host stated a fact; a document with none draws no
|
|
58
|
+
header at all, which is what keeps the pure-graph markup unchanged. */
|
|
59
|
+
.ig-header {
|
|
60
|
+
background: var(--ig-surface-2);
|
|
61
|
+
border-bottom: var(--ig-stroke) solid var(--ig-line);
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: var(--ig-space);
|
|
65
|
+
margin: 0;
|
|
66
|
+
padding: var(--ig-space-loose) var(--ig-space-wide);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.ig-header-lead {
|
|
46
70
|
align-items: center;
|
|
47
|
-
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
gap: var(--ig-space-snug);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* The segmented projection toggle §16a and §16b both draw. One rounded outline
|
|
76
|
+
around two buttons, the pressed one filled with the accent. */
|
|
77
|
+
.ig-toggle {
|
|
78
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
79
|
+
border-radius: var(--ig-radius);
|
|
80
|
+
display: inline-flex;
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.ig-toggle-option {
|
|
85
|
+
align-items: center;
|
|
86
|
+
background: none;
|
|
87
|
+
border: 0;
|
|
88
|
+
color: var(--ig-text-body);
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
font: inherit;
|
|
92
|
+
font-size: var(--ig-font-size-small);
|
|
93
|
+
gap: var(--ig-space-tight);
|
|
94
|
+
padding: var(--ig-space-micro) var(--ig-space-snug);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ig-toggle-option[aria-pressed='true'] {
|
|
98
|
+
background: var(--ig-accent);
|
|
99
|
+
color: var(--ig-bg);
|
|
100
|
+
font-weight: var(--ig-weight-strong);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.ig-header-top {
|
|
104
|
+
align-items: center;
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-wrap: wrap;
|
|
107
|
+
gap: var(--ig-space);
|
|
108
|
+
justify-content: space-between;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* The panel's own name, at the tracking the frame gives a frame-level label. */
|
|
112
|
+
.ig-header-label {
|
|
113
|
+
color: var(--ig-accent);
|
|
114
|
+
font-family: var(--ig-font-mono);
|
|
115
|
+
font-size: var(--ig-font-size-small);
|
|
116
|
+
letter-spacing: var(--ig-tracking-label);
|
|
117
|
+
text-transform: uppercase;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* THE COUNTS ARE CHIPS, NOT A SENTENCE. The frame gives each tally its own
|
|
121
|
+
outline and tints only the one a reader acts on — "how many could run right
|
|
122
|
+
now, against the cap" — so the accent is spent once instead of on a whole
|
|
123
|
+
line of muted prose. */
|
|
124
|
+
.ig-counts {
|
|
125
|
+
align-items: center;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-wrap: wrap;
|
|
128
|
+
gap: var(--ig-space-snug);
|
|
129
|
+
margin: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ig-count-chip {
|
|
133
|
+
background: var(--ig-bg);
|
|
134
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
135
|
+
border-radius: var(--ig-radius);
|
|
136
|
+
color: var(--ig-text-body);
|
|
137
|
+
font-family: var(--ig-font-mono);
|
|
138
|
+
font-size: var(--ig-font-size-small);
|
|
139
|
+
font-variant-numeric: tabular-nums;
|
|
140
|
+
padding: var(--ig-space-micro) var(--ig-space-snug);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.ig-count-chip[data-count='ready'] {
|
|
144
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-fill), transparent);
|
|
145
|
+
border-color: color-mix(in srgb, var(--ig-accent) var(--ig-tint-border), transparent);
|
|
146
|
+
color: var(--ig-text);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.ig-freshness {
|
|
150
|
+
align-items: center;
|
|
151
|
+
color: var(--ig-text-muted);
|
|
152
|
+
display: inline-flex;
|
|
153
|
+
font-family: var(--ig-font-mono);
|
|
154
|
+
font-size: var(--ig-font-size-small);
|
|
155
|
+
font-variant-numeric: tabular-nums;
|
|
156
|
+
gap: var(--ig-space-tight);
|
|
157
|
+
margin: 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* STALE GOES GOLD, as the design draws it. The gold this palette already holds
|
|
161
|
+
is the conflict state's — "the document moved upstream" — and a stale mirror
|
|
162
|
+
is that fact about the whole document, so the state hue is reused rather
|
|
163
|
+
than a token added for one word. No new token: the theme's token list is
|
|
164
|
+
the contract every host theme has to fill. */
|
|
165
|
+
.ig-freshness[data-stale='true'] {
|
|
166
|
+
color: var(--ig-state-conflict);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* A control the viewer publishes and does not wire: the UA button reset, so it
|
|
170
|
+
reads as the inline control the frame draws beside the stamp. */
|
|
171
|
+
.ig-refresh,
|
|
172
|
+
.ig-size {
|
|
173
|
+
background: none;
|
|
174
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
175
|
+
border-radius: var(--ig-radius);
|
|
176
|
+
color: var(--ig-text);
|
|
177
|
+
cursor: pointer;
|
|
178
|
+
font: inherit;
|
|
179
|
+
padding: var(--ig-space-micro) var(--ig-space-snug);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.ig-refresh:hover,
|
|
183
|
+
.ig-size:hover {
|
|
184
|
+
border-color: var(--ig-accent);
|
|
185
|
+
color: var(--ig-accent);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* ── the panel-level notice ────────────────────────────────────────────── */
|
|
189
|
+
|
|
190
|
+
/* WHAT THE HOST SAYS IS TRUE OF THE WHOLE PANEL, drawn between the NOW row and
|
|
191
|
+
the order it qualifies. Its own surface, so it reads as a statement about the
|
|
192
|
+
panel rather than as a row that lost its rank. */
|
|
193
|
+
.ig-notice {
|
|
194
|
+
align-items: flex-start;
|
|
195
|
+
background: var(--ig-surface-2);
|
|
196
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
197
|
+
border-radius: var(--ig-radius);
|
|
198
|
+
display: flex;
|
|
199
|
+
gap: var(--ig-space-snug);
|
|
200
|
+
justify-content: space-between;
|
|
201
|
+
padding: var(--ig-space-snug) var(--ig-space-loose);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.ig-notice-text {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
gap: var(--ig-space-micro);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.ig-notice-head {
|
|
211
|
+
align-items: center;
|
|
212
|
+
color: var(--ig-text);
|
|
213
|
+
display: flex;
|
|
214
|
+
gap: var(--ig-space-tight);
|
|
215
|
+
margin: 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.ig-notice-body {
|
|
219
|
+
color: var(--ig-text-body);
|
|
220
|
+
margin: 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* A COUNT, SO IT SITS ON THE FIGURE FACE. A progress figure is read as a number,
|
|
224
|
+
and the proportional face makes its digits wander the way a rank column's do. */
|
|
225
|
+
.ig-notice-progress {
|
|
226
|
+
color: var(--ig-text-muted);
|
|
227
|
+
font-family: var(--ig-font-mono);
|
|
228
|
+
font-size: var(--ig-font-size-small);
|
|
229
|
+
font-variant-numeric: tabular-nums;
|
|
230
|
+
margin: 0;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* THE SAME CONTROL RESET THE REFRESH BUTTON TAKES, and for the same reason: it
|
|
234
|
+
is published and not wired, so it must look like the inline control the frame
|
|
235
|
+
draws rather than like a UA button. The anchor arm gets it too — a host that
|
|
236
|
+
routes instead of acting should not get a different-looking affordance. */
|
|
237
|
+
.ig-notice-action {
|
|
238
|
+
background: none;
|
|
48
239
|
border: var(--ig-stroke) solid var(--ig-line);
|
|
49
240
|
border-radius: var(--ig-radius);
|
|
241
|
+
color: var(--ig-text);
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
font: inherit;
|
|
244
|
+
padding: var(--ig-space-micro) var(--ig-space-snug);
|
|
245
|
+
text-decoration: none;
|
|
246
|
+
white-space: nowrap;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.ig-notice-action:hover {
|
|
250
|
+
border-color: var(--ig-accent);
|
|
251
|
+
color: var(--ig-accent);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* GOLD ON FIRST IMPORT, and gold is the conflict state's hue — the same reuse
|
|
255
|
+
the stale stamp already makes, for the same reason: the token list is the
|
|
256
|
+
contract every host theme has to fill, so a token added for one state is a
|
|
257
|
+
theme every host has to revisit.
|
|
258
|
+
|
|
259
|
+
AND NOTHING FOR THE ERROR ARM. The design makes exactly one panel-level outline
|
|
260
|
+
claim, and it is this one; an error is drawn calm on purpose, because its own
|
|
261
|
+
sentence is that settings are safe and the pipeline is still running. A
|
|
262
|
+
failure-hued outline around the whole panel would say the opposite. */
|
|
263
|
+
.ig-viewer[data-ig-condition='importing'] {
|
|
264
|
+
outline: var(--ig-stroke) solid var(--ig-state-conflict);
|
|
265
|
+
outline-offset: var(--ig-space-micro);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.ig-notice[data-ig-condition='importing'] .ig-notice-head {
|
|
269
|
+
color: var(--ig-state-conflict);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.ig-notice[data-ig-condition='error'] .ig-notice-head {
|
|
273
|
+
color: var(--ig-state-failed);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* ── the adoption line ─────────────────────────────────────────────────── */
|
|
277
|
+
|
|
278
|
+
/* ONE QUIET LINE, which is the whole of what the design asks for here: the
|
|
279
|
+
day-one panel has to read complete and calm, and a block explaining what the
|
|
280
|
+
reader is missing is the opposite of calm. */
|
|
281
|
+
.ig-adoption {
|
|
282
|
+
align-items: center;
|
|
283
|
+
color: var(--ig-text-muted);
|
|
284
|
+
display: flex;
|
|
285
|
+
font-size: var(--ig-font-size-small);
|
|
286
|
+
gap: var(--ig-space-tight);
|
|
287
|
+
margin: 0;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* THE SENTENCE IS NOT THE LINK. Underlining the whole line made the quietest
|
|
291
|
+
element on the panel its loudest; the link is a short label beside it. */
|
|
292
|
+
.ig-adoption-text {
|
|
293
|
+
color: var(--ig-text-muted);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.ig-adoption-link {
|
|
297
|
+
color: var(--ig-text-muted);
|
|
298
|
+
margin-left: auto;
|
|
299
|
+
text-decoration: underline;
|
|
300
|
+
white-space: nowrap;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.ig-adoption-link:hover {
|
|
304
|
+
color: var(--ig-accent);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* PUBLISHED, NOT PERFORMED. The viewer never removes its own line; the host
|
|
308
|
+
re-renders without the note. */
|
|
309
|
+
.ig-adoption-dismiss {
|
|
310
|
+
background: none;
|
|
311
|
+
border: 0;
|
|
312
|
+
color: var(--ig-text-muted);
|
|
313
|
+
cursor: pointer;
|
|
314
|
+
font: inherit;
|
|
315
|
+
padding: 0;
|
|
316
|
+
text-decoration: underline;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.ig-adoption-dismiss:hover {
|
|
320
|
+
color: var(--ig-accent);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* ── working now ───────────────────────────────────────────────────────── */
|
|
324
|
+
|
|
325
|
+
.ig-now {
|
|
326
|
+
list-style: none;
|
|
327
|
+
margin: 0;
|
|
328
|
+
padding: 0;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* A BAND, NOT A CARD. The frame runs it full-bleed across the panel with a
|
|
332
|
+
wash and an accent rail down its leading edge — the same treatment the shell
|
|
333
|
+
gives anything in flight — so it reads as a state of the panel rather than
|
|
334
|
+
as the first row of the order. */
|
|
335
|
+
.ig-now-row {
|
|
336
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-wash), transparent);
|
|
337
|
+
border-bottom: var(--ig-stroke) solid var(--ig-line);
|
|
338
|
+
box-shadow: inset var(--ig-band-rail) 0 0 var(--ig-accent);
|
|
50
339
|
column-gap: var(--ig-space);
|
|
51
340
|
display: grid;
|
|
52
|
-
grid-template-columns: auto
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
341
|
+
grid-template-columns: auto 1fr auto;
|
|
342
|
+
align-items: center;
|
|
343
|
+
padding: var(--ig-space) var(--ig-space-wide);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.ig-now-mark {
|
|
347
|
+
background: var(--ig-accent);
|
|
348
|
+
border-radius: var(--ig-radius-small);
|
|
349
|
+
color: var(--ig-bg);
|
|
350
|
+
font-family: var(--ig-font-mono);
|
|
351
|
+
font-size: var(--ig-font-size-pill);
|
|
352
|
+
font-weight: var(--ig-weight-strong);
|
|
353
|
+
letter-spacing: var(--ig-tracking-pill);
|
|
354
|
+
padding: var(--ig-space-micro) var(--ig-space-tight);
|
|
355
|
+
text-transform: uppercase;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.ig-now-phase {
|
|
359
|
+
align-items: center;
|
|
360
|
+
color: var(--ig-accent);
|
|
361
|
+
display: inline-flex;
|
|
362
|
+
font-family: var(--ig-font-mono);
|
|
363
|
+
font-size: var(--ig-font-size-small);
|
|
364
|
+
gap: var(--ig-space-tight);
|
|
365
|
+
white-space: nowrap;
|
|
56
366
|
}
|
|
57
367
|
|
|
368
|
+
/* The pulse is the frame's, and it is the one moving thing in the panel. */
|
|
369
|
+
.ig-now-pulse {
|
|
370
|
+
background: var(--ig-accent);
|
|
371
|
+
block-size: var(--ig-space-tight);
|
|
372
|
+
border-radius: 50%;
|
|
373
|
+
display: inline-block;
|
|
374
|
+
inline-size: var(--ig-space-tight);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/* ── the order ─────────────────────────────────────────────────────────── */
|
|
378
|
+
|
|
379
|
+
/* TWO COLUMNS, WHICH IS THE FRAME'S GRID EXACTLY. The rank track holds the
|
|
380
|
+
figure and the readiness dot stacked, and everything else is one body
|
|
381
|
+
column, so a row has exactly two children and nothing can auto-place into
|
|
382
|
+
the rank track and set its width. That was a real defect: a single
|
|
383
|
+
relationship badge left unplaced widened the rank column for the whole list
|
|
384
|
+
and squeezed every title to pay for it. */
|
|
385
|
+
.ig-slot {
|
|
386
|
+
border-bottom: var(--ig-stroke) solid var(--ig-line);
|
|
387
|
+
column-gap: var(--ig-space);
|
|
388
|
+
display: grid;
|
|
389
|
+
grid-template-columns: var(--ig-rank-column) 1fr;
|
|
390
|
+
min-height: var(--ig-row-min-height);
|
|
391
|
+
padding: var(--ig-row-padding-block) var(--ig-space-wide);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* THE ONE ROW GROUND THE FRAME DRAWS, and it is not a stripe. A together unit
|
|
395
|
+
is the compound station, and the tint says so; the other ranked rows carry
|
|
396
|
+
no background at all. */
|
|
397
|
+
.ig-slot[data-unit='true'] {
|
|
398
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-unit), transparent);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* A HELD ROW IS HATCHED, NOT DASHED. It keeps its position in the sequence —
|
|
402
|
+
"why isn't my P1 running" is answerable in place — so it must read as
|
|
403
|
+
unavailable without leaving the grid the rows above and below hang off. A
|
|
404
|
+
dashed border around one row breaks that alignment; a ground does not. */
|
|
58
405
|
.ig-slot[data-held='true'] {
|
|
59
|
-
background:
|
|
60
|
-
|
|
406
|
+
background-image: repeating-linear-gradient(
|
|
407
|
+
135deg,
|
|
408
|
+
color-mix(in srgb, var(--ig-text) var(--ig-tint-unit), transparent) 0 var(--ig-space-tight),
|
|
409
|
+
transparent var(--ig-space-tight) calc(var(--ig-space-tight) * 2)
|
|
410
|
+
);
|
|
61
411
|
}
|
|
62
412
|
|
|
63
413
|
.ig-slot[aria-current='true'] {
|
|
64
|
-
|
|
414
|
+
box-shadow: inset var(--ig-band-rail) 0 0 var(--ig-accent);
|
|
65
415
|
}
|
|
66
416
|
|
|
67
417
|
/* A CANVAS-OWNED NODE IS SELECTABLE TOO, and only the rail rows had a selected
|
|
@@ -75,16 +425,43 @@ export const viewerStylesheet = `
|
|
|
75
425
|
stroke-width: calc(var(--ig-stroke) * 2);
|
|
76
426
|
}
|
|
77
427
|
|
|
428
|
+
/* The rank track: figure over dot, centred, so the title column starts at one
|
|
429
|
+
x on every row whether or not the row has a number to print. */
|
|
430
|
+
.ig-rank-cell {
|
|
431
|
+
align-items: center;
|
|
432
|
+
display: flex;
|
|
433
|
+
flex-direction: column;
|
|
434
|
+
gap: var(--ig-space-tight);
|
|
435
|
+
}
|
|
436
|
+
|
|
78
437
|
.ig-rank {
|
|
79
438
|
color: var(--ig-text);
|
|
80
439
|
font-family: var(--ig-font-mono);
|
|
440
|
+
font-size: var(--ig-font-size-rank);
|
|
81
441
|
font-variant-numeric: tabular-nums;
|
|
82
|
-
|
|
83
|
-
|
|
442
|
+
font-weight: var(--ig-weight-strong);
|
|
443
|
+
line-height: 1;
|
|
84
444
|
}
|
|
85
445
|
|
|
86
446
|
.ig-rank[data-held='true'] {
|
|
87
447
|
color: var(--ig-text-muted);
|
|
448
|
+
font-weight: var(--ig-weight-regular);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.ig-row-body {
|
|
452
|
+
display: flex;
|
|
453
|
+
flex-direction: column;
|
|
454
|
+
gap: var(--ig-space-snug);
|
|
455
|
+
min-width: 0;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* The title, the identity and the two-line pair they form: 2px apart, which is
|
|
459
|
+
what makes them read as one object rather than as two rows of metadata. */
|
|
460
|
+
.ig-row-head {
|
|
461
|
+
display: flex;
|
|
462
|
+
flex-direction: column;
|
|
463
|
+
gap: var(--ig-space-micro);
|
|
464
|
+
min-width: 0;
|
|
88
465
|
}
|
|
89
466
|
|
|
90
467
|
/* ── readiness stations ────────────────────────────────────────────────── */
|
|
@@ -93,7 +470,6 @@ export const viewerStylesheet = `
|
|
|
93
470
|
block-size: var(--ig-station-size);
|
|
94
471
|
border: var(--ig-stroke) solid var(--ig-station-held);
|
|
95
472
|
border-radius: 50%;
|
|
96
|
-
box-shadow: 0 0 0 var(--ig-station-halo) var(--ig-bg);
|
|
97
473
|
display: inline-block;
|
|
98
474
|
inline-size: var(--ig-station-size);
|
|
99
475
|
}
|
|
@@ -116,34 +492,84 @@ export const viewerStylesheet = `
|
|
|
116
492
|
|
|
117
493
|
/* ── titles, identity, provenance ──────────────────────────────────────── */
|
|
118
494
|
|
|
495
|
+
/* NOTHING TRUNCATES. The ellipsis this rule used to carry, against a FIXED row
|
|
496
|
+
height, is the direct cause of the frame's titles arriving on screen as
|
|
497
|
+
"Retype the ca…" — a panel whose job is to say what the work is, declining
|
|
498
|
+
to say what the work is. A row grows instead; --ig-row-min-height is a
|
|
499
|
+
floor, not a height. anywhere covers the one case wrapping cannot: an
|
|
500
|
+
unbroken token wider than the column, which would otherwise overflow the
|
|
501
|
+
panel rather than the line. */
|
|
119
502
|
.ig-title {
|
|
120
503
|
color: var(--ig-text);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
504
|
+
font-size: var(--ig-font-size-row);
|
|
505
|
+
overflow-wrap: anywhere;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.ig-slot[data-held='true'] .ig-title,
|
|
509
|
+
.ig-footer .ig-title {
|
|
510
|
+
color: var(--ig-text-body);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* A held row's CONTENT recedes, not its position. The frame dims the body and
|
|
514
|
+
leaves the rank track at full strength, so the row still reads as occupying
|
|
515
|
+
the slot it would have taken. */
|
|
516
|
+
.ig-slot[data-held='true'] .ig-row-body {
|
|
517
|
+
opacity: 0.72;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/* The isolated-issue tally sits directly on the panel, outside the padded
|
|
521
|
+
groups, so it carries the panel's own inset rather than none. */
|
|
522
|
+
.ig-count {
|
|
523
|
+
margin: 0;
|
|
524
|
+
padding: var(--ig-space) var(--ig-space-wide);
|
|
124
525
|
}
|
|
125
526
|
|
|
126
527
|
.ig-id,
|
|
127
528
|
.ig-count {
|
|
128
529
|
color: var(--ig-text-muted);
|
|
129
530
|
font-family: var(--ig-font-mono);
|
|
531
|
+
font-size: var(--ig-font-size-small);
|
|
130
532
|
font-variant-numeric: tabular-nums;
|
|
131
533
|
}
|
|
132
534
|
|
|
133
535
|
.ig-link {
|
|
134
|
-
color:
|
|
536
|
+
color: inherit;
|
|
135
537
|
text-decoration: none;
|
|
136
538
|
}
|
|
137
539
|
|
|
138
540
|
.ig-link:hover {
|
|
541
|
+
color: var(--ig-accent);
|
|
139
542
|
text-decoration: underline;
|
|
140
543
|
}
|
|
141
544
|
|
|
545
|
+
/* THE PROVENANCE LINE IS NOT MUTED. It is the answer to "why is this here",
|
|
546
|
+
which is the panel's whole reason to exist, so the frame gives it body text
|
|
547
|
+
and lifts the named parts to the brightest ink on the page. Muting the whole
|
|
548
|
+
sentence — which is what shipped — files the explanation under decoration. */
|
|
142
549
|
.ig-provenance,
|
|
143
|
-
.ig-hold
|
|
144
|
-
|
|
550
|
+
.ig-hold,
|
|
551
|
+
.ig-caveat {
|
|
552
|
+
align-items: baseline;
|
|
553
|
+
color: var(--ig-text-body);
|
|
554
|
+
display: flex;
|
|
555
|
+
font-family: var(--ig-font-mono);
|
|
145
556
|
font-size: var(--ig-font-size-small);
|
|
146
|
-
|
|
557
|
+
gap: var(--ig-space-tight);
|
|
558
|
+
margin: 0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.ig-provenance .ig-id,
|
|
562
|
+
.ig-hold .ig-id,
|
|
563
|
+
.ig-caveat .ig-id {
|
|
564
|
+
color: var(--ig-text);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/* The turnstile the frame puts in front of every explanation, so the line reads
|
|
568
|
+
as subordinate to the row above it without being dimmed. */
|
|
569
|
+
.ig-turn {
|
|
570
|
+
color: var(--ig-text-muted);
|
|
571
|
+
font-size: var(--ig-font-size-micro);
|
|
572
|
+
flex: 0 0 auto;
|
|
147
573
|
}
|
|
148
574
|
|
|
149
575
|
.ig-strike {
|
|
@@ -152,70 +578,224 @@ export const viewerStylesheet = `
|
|
|
152
578
|
|
|
153
579
|
/* ── edge badges ───────────────────────────────────────────────────────── */
|
|
154
580
|
|
|
155
|
-
/* SPANNED FROM THE TITLE COLUMN, LIKE EVERY OTHER FULL-WIDTH ROW MEMBER. Left
|
|
156
|
-
unplaced this was the fifth child of a four-column grid, so it auto-placed
|
|
157
|
-
into column ONE of a second row — the rank track, an auto-sized column that
|
|
158
|
-
takes the width of its widest item. One relationship badge then set the width
|
|
159
|
-
of the rank column for the whole row, pushing the station and title across
|
|
160
|
-
and squeezing the title to pay for it. Badges belong with the row's other
|
|
161
|
-
metadata, which is what 3 / -1 already means here for provenance and holds.
|
|
162
|
-
(No backticks in this file: the stylesheet is a template literal.) */
|
|
163
581
|
.ig-badges {
|
|
164
582
|
display: flex;
|
|
165
583
|
flex-wrap: wrap;
|
|
166
584
|
gap: var(--ig-space-tight);
|
|
167
|
-
grid-column: 3 / -1;
|
|
168
585
|
}
|
|
169
586
|
|
|
587
|
+
/* A TINTED CHIP, NOT A BARE OUTLINE. The frame fills every relationship chip
|
|
588
|
+
with its own hue at a low alpha inside a heavier border of the same hue;
|
|
589
|
+
drawn as an outline alone the badge row reads as a row of empty boxes, and
|
|
590
|
+
the hue channel carries a third of the weight the design gives it. The two
|
|
591
|
+
alphas are the theme's, so a host retinting a relationship retints its chip. */
|
|
170
592
|
.ig-badge {
|
|
171
593
|
align-items: center;
|
|
172
|
-
|
|
173
|
-
colours deliberately — see below. Left as currentColor the border would
|
|
174
|
-
follow the text to --ig-text and the hue channel would vanish from the
|
|
175
|
-
badge entirely, which is the opposite of the fix. */
|
|
594
|
+
background: var(--ig-surface-2);
|
|
176
595
|
border: var(--ig-stroke) solid var(--ig-line);
|
|
177
|
-
border-radius: var(--ig-radius);
|
|
596
|
+
border-radius: var(--ig-radius-small);
|
|
178
597
|
color: var(--ig-text);
|
|
179
598
|
display: inline-flex;
|
|
180
|
-
font-
|
|
599
|
+
font-family: var(--ig-font-mono);
|
|
600
|
+
font-size: var(--ig-font-size-micro);
|
|
181
601
|
gap: var(--ig-space-tight);
|
|
182
|
-
padding:
|
|
602
|
+
padding: var(--ig-space-micro) var(--ig-space-tight);
|
|
183
603
|
}
|
|
184
604
|
|
|
185
|
-
/* THE HUE IS A BORDER
|
|
605
|
+
/* THE HUE IS A BORDER AND A FILL HERE, NOT A TEXT COLOUR — the theme holds the
|
|
186
606
|
edge hues to the 3:1 NON-TEXT bar, and says so where it defines them, so
|
|
187
|
-
painting badge LABELS with them
|
|
607
|
+
painting badge LABELS with them contradicts the palette's own claim. It was
|
|
188
608
|
not merely theoretical: at this size duplicate-of measured 3.98:1 on
|
|
189
609
|
--ig-surface and decomposed-from 4.37:1, both under the 4.5:1 the text test
|
|
190
|
-
asserts for every text colour. The label
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
610
|
+
asserts for every text colour. The label takes --ig-text, which that test
|
|
611
|
+
already proves on all three surfaces, and the hue keeps the non-text use it
|
|
612
|
+
was measured for. This is a DELIBERATE DEPARTURE from the frame, which tints
|
|
613
|
+
its chip labels; the frame's own colour-blind-safety clause says hue is one
|
|
614
|
+
of four redundant channels, and here it is carried by two of them.
|
|
615
|
+
NO CHANNEL IS LOST. The dash pattern and the glyph are untouched, and the
|
|
195
616
|
vocabulary test independently proves all five stay distinguishable with hue
|
|
196
617
|
removed ENTIRELY, which is the stronger claim. */
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
.
|
|
200
|
-
|
|
201
|
-
|
|
618
|
+
/* WRITTEN OUT PER EDGE RATHER THAN THROUGH ONE INTERMEDIATE PROPERTY. A
|
|
619
|
+
an intermediate --ig-badge-hue set here and read here would be a property no
|
|
620
|
+
theme and no layout declares, and styles.test.ts refuses those on purpose:
|
|
621
|
+
the whole point of that guard is that every var() in this file names
|
|
622
|
+
something a host or the layout actually sets. */
|
|
623
|
+
.ig-badge[data-edge='blocked-by'] {
|
|
624
|
+
background: color-mix(in srgb, var(--ig-edge-blocked-by) var(--ig-tint-fill), transparent);
|
|
625
|
+
border-color: color-mix(in srgb, var(--ig-edge-blocked-by) var(--ig-tint-border), transparent);
|
|
626
|
+
border-style: solid;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.ig-badge[data-edge='serialize-with'] {
|
|
630
|
+
background: color-mix(in srgb, var(--ig-edge-serialize-with) var(--ig-tint-fill), transparent);
|
|
631
|
+
border-color: color-mix(in srgb, var(--ig-edge-serialize-with) var(--ig-tint-border), transparent);
|
|
632
|
+
border-style: double;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.ig-badge[data-edge='together-with'] {
|
|
636
|
+
background: color-mix(in srgb, var(--ig-edge-together-with) var(--ig-tint-fill), transparent);
|
|
637
|
+
border-color: color-mix(in srgb, var(--ig-edge-together-with) var(--ig-tint-border), transparent);
|
|
638
|
+
border-style: solid;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.ig-badge[data-edge='duplicate-of'] {
|
|
642
|
+
background: color-mix(in srgb, var(--ig-edge-duplicate-of) var(--ig-tint-fill), transparent);
|
|
643
|
+
border-color: color-mix(in srgb, var(--ig-edge-duplicate-of) var(--ig-tint-border), transparent);
|
|
644
|
+
border-style: dotted;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.ig-badge[data-edge='decomposed-from'] {
|
|
648
|
+
background: color-mix(in srgb, var(--ig-edge-decomposed-from) var(--ig-tint-fill), transparent);
|
|
649
|
+
border-color: color-mix(in srgb, var(--ig-edge-decomposed-from) var(--ig-tint-border), transparent);
|
|
650
|
+
border-style: dashed;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/* A PROMOTION IS THE ONE CHIP THE FRAME ACCENTS. It is the most interesting
|
|
654
|
+
event the panel can show — a low tier pulled to the top because it blocks a
|
|
655
|
+
high one — and the design spends its accent on exactly that. */
|
|
656
|
+
.ig-badge[data-priority='promoted'] {
|
|
657
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-fill), transparent);
|
|
658
|
+
border-color: color-mix(in srgb, var(--ig-accent) var(--ig-tint-border), transparent);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.ig-badge[data-evidence='verified'] {
|
|
662
|
+
background: color-mix(in srgb, var(--ig-station-ready) var(--ig-tint-fill), transparent);
|
|
663
|
+
border-color: color-mix(in srgb, var(--ig-station-ready) var(--ig-tint-border), transparent);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/* A caveat or hold-label chip carries no relationship hue: it is a word, not
|
|
667
|
+
an edge, so it keeps the line colour the plain badge has. */
|
|
668
|
+
.ig-badge[data-caveat],
|
|
669
|
+
.ig-badge[data-hold] {
|
|
670
|
+
color: var(--ig-text-body);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.ig-badge[data-caveat='preview-only'] {
|
|
674
|
+
border-color: color-mix(in srgb, var(--ig-state-conflict) var(--ig-tint-border), transparent);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
.ig-badge[data-not-ready='true'] {
|
|
678
|
+
background: color-mix(in srgb, var(--ig-edge-blocked-by) var(--ig-tint-fill), transparent);
|
|
679
|
+
border-color: color-mix(in srgb, var(--ig-edge-blocked-by) var(--ig-tint-border), transparent);
|
|
680
|
+
}
|
|
202
681
|
|
|
203
682
|
.ig-glyph {
|
|
204
683
|
font-family: var(--ig-font-mono);
|
|
205
684
|
}
|
|
206
685
|
|
|
686
|
+
/* ── the together unit: one rank, two issues ───────────────────────────── */
|
|
687
|
+
|
|
688
|
+
.ig-unit-mark {
|
|
689
|
+
align-items: center;
|
|
690
|
+
display: flex;
|
|
691
|
+
gap: var(--ig-space-snug);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.ig-unit-pill {
|
|
695
|
+
background: var(--ig-accent);
|
|
696
|
+
border-radius: var(--ig-radius-small);
|
|
697
|
+
color: var(--ig-bg);
|
|
698
|
+
font-family: var(--ig-font-mono);
|
|
699
|
+
font-size: var(--ig-font-size-pill);
|
|
700
|
+
font-weight: var(--ig-weight-strong);
|
|
701
|
+
letter-spacing: var(--ig-tracking-badge);
|
|
702
|
+
padding: var(--ig-space-micro) var(--ig-space-tight);
|
|
703
|
+
text-transform: uppercase;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
.ig-unit-note {
|
|
707
|
+
color: var(--ig-text-muted);
|
|
708
|
+
font-family: var(--ig-font-mono);
|
|
709
|
+
font-size: var(--ig-font-size-micro);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/* THE MEMBERS GET ONE LINE EACH. Joining them with a separator — which is what
|
|
713
|
+
shipped — makes a two-issue unit read as one issue with a long title, and
|
|
714
|
+
the unit is the one place the design draws an enclosure to say the opposite. */
|
|
715
|
+
/* THE UNIT'S ENCLOSURE IS THE together-with MARK. It is drawn at the
|
|
716
|
+
connector's hairline width, which is what that token has always meant: finer
|
|
717
|
+
than an ordinary edge, so the enclosure stays the primary read. */
|
|
718
|
+
.ig-unit {
|
|
719
|
+
border: var(--ig-stroke-connector) solid color-mix(in srgb, var(--ig-edge-together-with) var(--ig-tint-border), transparent);
|
|
720
|
+
border-radius: var(--ig-radius);
|
|
721
|
+
list-style: none;
|
|
722
|
+
margin: 0;
|
|
723
|
+
overflow: hidden;
|
|
724
|
+
padding: 0;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.ig-unit-member {
|
|
728
|
+
display: flex;
|
|
729
|
+
flex-direction: column;
|
|
730
|
+
gap: var(--ig-space-micro);
|
|
731
|
+
padding: var(--ig-space-snug) var(--ig-space);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.ig-unit-member + .ig-unit-member {
|
|
735
|
+
border-top: var(--ig-stroke) solid var(--ig-line);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.ig-unit-member .ig-title {
|
|
739
|
+
font-size: var(--ig-font-size-compact);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.ig-unit-member .ig-id {
|
|
743
|
+
font-size: var(--ig-font-size-meta);
|
|
744
|
+
}
|
|
745
|
+
|
|
207
746
|
/* ── the footer group: holds that earn no rank slot ────────────────────── */
|
|
208
747
|
|
|
209
748
|
.ig-footer {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
749
|
+
background: var(--ig-surface-2);
|
|
750
|
+
padding: var(--ig-space) var(--ig-space-wide);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.ig-footer-head {
|
|
754
|
+
align-items: center;
|
|
755
|
+
display: flex;
|
|
756
|
+
gap: var(--ig-space);
|
|
757
|
+
justify-content: space-between;
|
|
213
758
|
}
|
|
214
759
|
|
|
215
760
|
.ig-footer-title {
|
|
761
|
+
color: var(--ig-text-body);
|
|
762
|
+
font-size: var(--ig-font-size-compact);
|
|
763
|
+
margin: 0;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.ig-footer-labels {
|
|
216
767
|
color: var(--ig-text-muted);
|
|
217
|
-
font-
|
|
218
|
-
|
|
768
|
+
font-family: var(--ig-font-mono);
|
|
769
|
+
font-size: var(--ig-font-size-meta);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/* ONE LINE EACH, and the frame is explicit about why: these are not facts
|
|
773
|
+
about the work, so they earn no rank slot and no explanation block. A full
|
|
774
|
+
row here — station, badges, provenance — was claiming the opposite. */
|
|
775
|
+
.ig-footer .ig-list {
|
|
776
|
+
display: flex;
|
|
777
|
+
flex-direction: column;
|
|
778
|
+
gap: var(--ig-space-snug);
|
|
779
|
+
margin-top: var(--ig-space);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
.ig-footer-row {
|
|
783
|
+
align-items: center;
|
|
784
|
+
display: flex;
|
|
785
|
+
gap: var(--ig-space-snug);
|
|
786
|
+
opacity: 0.72;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.ig-footer-row .ig-title {
|
|
790
|
+
font-size: var(--ig-font-size-compact);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
.ig-footer-row .ig-id {
|
|
794
|
+
font-size: var(--ig-font-size-meta);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
.ig-footer-row[aria-current='true'] {
|
|
798
|
+
opacity: 1;
|
|
219
799
|
}
|
|
220
800
|
|
|
221
801
|
/* ── the graph canvas ──────────────────────────────────────────────────── */
|
|
@@ -239,7 +819,26 @@ export const viewerStylesheet = `
|
|
|
239
819
|
inline-size: var(--ig-stage-w);
|
|
240
820
|
}
|
|
241
821
|
|
|
242
|
-
/* The
|
|
822
|
+
/* The three column headers, which say what each column is FOR. Without them
|
|
823
|
+
the gutters read as two more piles of issues rather than as the two answers
|
|
824
|
+
the spine deliberately keeps off itself. */
|
|
825
|
+
.ig-column-head {
|
|
826
|
+
color: var(--ig-text-muted);
|
|
827
|
+
font-family: var(--ig-font-mono);
|
|
828
|
+
font-size: var(--ig-font-size-pill);
|
|
829
|
+
letter-spacing: var(--ig-tracking-group);
|
|
830
|
+
position: absolute;
|
|
831
|
+
text-transform: uppercase;
|
|
832
|
+
inset-block-start: var(--ig-space-snug);
|
|
833
|
+
inset-inline-start: var(--ig-col-x);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.ig-column-head[data-column='spine'] {
|
|
837
|
+
color: var(--ig-accent);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* The node cards and the station column, sitting on the coordinates the layout
|
|
841
|
+
computed. */
|
|
243
842
|
.ig-rail {
|
|
244
843
|
inset: 0;
|
|
245
844
|
pointer-events: none;
|
|
@@ -247,16 +846,147 @@ export const viewerStylesheet = `
|
|
|
247
846
|
}
|
|
248
847
|
|
|
249
848
|
.ig-rail-row {
|
|
250
|
-
block-size:
|
|
849
|
+
block-size: auto;
|
|
251
850
|
inline-size: var(--ig-row-w);
|
|
252
851
|
inset-block-start: var(--ig-row-y);
|
|
253
852
|
inset-inline-start: var(--ig-row-x);
|
|
254
|
-
|
|
255
|
-
min-block-size: 0;
|
|
853
|
+
min-block-size: var(--ig-row-h);
|
|
256
854
|
pointer-events: auto;
|
|
257
855
|
position: absolute;
|
|
258
856
|
}
|
|
259
857
|
|
|
858
|
+
/* A CARD, NOT A LABELLED RECTANGLE. Drawing the node's text in SVG is what
|
|
859
|
+
forced every title through a width fit and out the other side truncated; an
|
|
860
|
+
HTML card wraps, so the acceptance criterion "nothing truncates" is met by
|
|
861
|
+
construction rather than by choosing a wider box. */
|
|
862
|
+
.ig-card {
|
|
863
|
+
background: var(--ig-surface);
|
|
864
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
865
|
+
border-radius: var(--ig-radius-large);
|
|
866
|
+
display: flex;
|
|
867
|
+
flex-direction: column;
|
|
868
|
+
gap: var(--ig-space-tight);
|
|
869
|
+
padding: var(--ig-space) var(--ig-space);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
.ig-card .ig-title {
|
|
873
|
+
font-size: var(--ig-font-size-compact);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.ig-card .ig-id {
|
|
877
|
+
font-size: var(--ig-font-size-meta);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.ig-card[data-column='left'] {
|
|
881
|
+
background: var(--ig-surface-2);
|
|
882
|
+
border-color: color-mix(in srgb, var(--ig-edge-blocked-by) var(--ig-tint-border), transparent);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/* NEVER WORKED READS AS NEVER DRAWN IN. The right gutter's two node states are
|
|
886
|
+
the design's own: a dashed provenance origin and a dotted duplicate, both on
|
|
887
|
+
no ground at all, so the eye files them as outside the order before reading
|
|
888
|
+
a word. */
|
|
889
|
+
.ig-card[data-column='right'] {
|
|
890
|
+
background: transparent;
|
|
891
|
+
border-style: dashed;
|
|
892
|
+
opacity: 0.8;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.ig-card[data-exclusion='true'] {
|
|
896
|
+
border-style: dotted;
|
|
897
|
+
border-color: color-mix(in srgb, var(--ig-edge-duplicate-of) var(--ig-tint-border), transparent);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
.ig-card[data-held='true'] {
|
|
901
|
+
background: transparent;
|
|
902
|
+
border-style: dashed;
|
|
903
|
+
opacity: 0.75;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
.ig-card[data-now='true'] {
|
|
907
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-wash), transparent);
|
|
908
|
+
border-color: color-mix(in srgb, var(--ig-accent) var(--ig-tint-border), transparent);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
.ig-card[data-unit='true'] {
|
|
912
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-unit), transparent);
|
|
913
|
+
border-color: var(--ig-accent);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
.ig-rail-row[aria-current='true'] .ig-card {
|
|
917
|
+
border-color: var(--ig-accent);
|
|
918
|
+
box-shadow: 0 0 0 var(--ig-band-rail) color-mix(in srgb, var(--ig-accent) var(--ig-tint-border), transparent);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/* The station column: a disc on the spine, carrying the rank the row would
|
|
922
|
+
otherwise have to be read for. */
|
|
923
|
+
.ig-spine-station {
|
|
924
|
+
align-items: center;
|
|
925
|
+
background: var(--ig-bg);
|
|
926
|
+
block-size: var(--ig-station-box);
|
|
927
|
+
border: calc(var(--ig-stroke) * 2) solid var(--ig-station-ready);
|
|
928
|
+
border-radius: 50%;
|
|
929
|
+
box-shadow: 0 0 0 var(--ig-station-halo) var(--ig-bg);
|
|
930
|
+
color: var(--ig-station-pending);
|
|
931
|
+
display: flex;
|
|
932
|
+
font-family: var(--ig-font-mono);
|
|
933
|
+
font-size: var(--ig-font-size-small);
|
|
934
|
+
font-weight: var(--ig-weight-heavy);
|
|
935
|
+
inline-size: var(--ig-station-box);
|
|
936
|
+
inset-block-start: var(--ig-station-y);
|
|
937
|
+
inset-inline-start: var(--ig-station-x);
|
|
938
|
+
justify-content: center;
|
|
939
|
+
pointer-events: none;
|
|
940
|
+
position: absolute;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.ig-spine-station[data-fill='filled'] {
|
|
944
|
+
background: var(--ig-station-ready);
|
|
945
|
+
color: var(--ig-bg);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.ig-spine-station[data-fill='hollow'] {
|
|
949
|
+
border-color: var(--ig-station-ready);
|
|
950
|
+
color: var(--ig-station-ready);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.ig-spine-station[data-fill='dashed'] {
|
|
954
|
+
border-style: dashed;
|
|
955
|
+
border-width: var(--ig-stroke);
|
|
956
|
+
border-color: var(--ig-station-held);
|
|
957
|
+
color: var(--ig-text-muted);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/* The serialize hold is gold in the frame, on the station as well as the arc:
|
|
961
|
+
a station that waits for a PEER is a different fact from one that waits for
|
|
962
|
+
a rank above it. */
|
|
963
|
+
/* THE RING TAKES THE HUE, THE DIGIT DOES NOT. §16b draws both in gold, and the
|
|
964
|
+
theme holds every edge hue to the 3:1 NON-TEXT bar — so painting the rank
|
|
965
|
+
figure with it makes a claim the palette does not support, on the one glyph
|
|
966
|
+
in the station a reader has to actually read. The hue keeps the ring, which
|
|
967
|
+
is the channel it was measured for; the number keeps the ink every text
|
|
968
|
+
contrast test already proves. */
|
|
969
|
+
.ig-spine-station[data-wait='serialize'] {
|
|
970
|
+
border-color: var(--ig-edge-serialize-with);
|
|
971
|
+
color: var(--ig-text);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.ig-spine {
|
|
975
|
+
stroke: var(--ig-line);
|
|
976
|
+
stroke-width: calc(var(--ig-stroke) * 2);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
.ig-more {
|
|
980
|
+
color: var(--ig-text-muted);
|
|
981
|
+
font-family: var(--ig-font-mono);
|
|
982
|
+
font-size: var(--ig-font-size-micro);
|
|
983
|
+
inline-size: var(--ig-row-w);
|
|
984
|
+
inset-block-start: var(--ig-row-y);
|
|
985
|
+
inset-inline-start: var(--ig-row-x);
|
|
986
|
+
position: absolute;
|
|
987
|
+
text-align: center;
|
|
988
|
+
}
|
|
989
|
+
|
|
260
990
|
.ig-node {
|
|
261
991
|
fill: var(--ig-surface);
|
|
262
992
|
stroke: var(--ig-line);
|
|
@@ -286,18 +1016,15 @@ export const viewerStylesheet = `
|
|
|
286
1016
|
.ig-edge[data-edge='decomposed-from'] { stroke: var(--ig-edge-decomposed-from); }
|
|
287
1017
|
|
|
288
1018
|
/* The dash pattern is set per element from the edge vocabulary, never here —
|
|
289
|
-
one source for the channel the colour-blind-safety claim rests on.
|
|
1019
|
+
one source for the channel the colour-blind-safety claim rests on. Drawn only
|
|
1020
|
+
in the legend now: a together unit is ONE card with its members listed inside
|
|
1021
|
+
it, so the canvas has no pair of boxes to surround. */
|
|
290
1022
|
.ig-enclosure {
|
|
291
1023
|
fill: none;
|
|
292
1024
|
stroke: var(--ig-edge-together-with);
|
|
293
1025
|
stroke-width: var(--ig-stroke);
|
|
294
1026
|
}
|
|
295
1027
|
|
|
296
|
-
.ig-connector {
|
|
297
|
-
stroke: var(--ig-edge-together-with);
|
|
298
|
-
stroke-width: var(--ig-stroke-connector);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
1028
|
/* currentColor on the marker resolves to the inherited text colour, not to the
|
|
302
1029
|
edge's stroke — so a terminal has to be given the hue explicitly or it renders
|
|
303
1030
|
in body text and the fourth channel silently collapses. */
|
|
@@ -320,6 +1047,7 @@ export const viewerStylesheet = `
|
|
|
320
1047
|
border: var(--ig-stroke) solid var(--ig-line);
|
|
321
1048
|
border-radius: var(--ig-radius);
|
|
322
1049
|
color: var(--ig-text-body);
|
|
1050
|
+
margin: var(--ig-space-wide);
|
|
323
1051
|
padding: var(--ig-space);
|
|
324
1052
|
}
|
|
325
1053
|
|
|
@@ -359,6 +1087,10 @@ export const viewerStylesheet = `
|
|
|
359
1087
|
padding: 0;
|
|
360
1088
|
}
|
|
361
1089
|
|
|
1090
|
+
.ig-tree {
|
|
1091
|
+
padding: var(--ig-space) var(--ig-space-wide);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
362
1094
|
.ig-tree .ig-list {
|
|
363
1095
|
border-left: var(--ig-stroke) dashed var(--ig-edge-decomposed-from);
|
|
364
1096
|
margin-left: var(--ig-space);
|
|
@@ -371,19 +1103,44 @@ export const viewerStylesheet = `
|
|
|
371
1103
|
|
|
372
1104
|
/* ── legend ────────────────────────────────────────────────────────────── */
|
|
373
1105
|
|
|
1106
|
+
/* A FOOTER BAR, WHERE §16b PUTS IT, and worded rather than glyph-only. It sits
|
|
1107
|
+
under the drawing it explains, carries a drawn sample of each line so the
|
|
1108
|
+
dash and terminal channels are legible cold, and ends with the readiness key
|
|
1109
|
+
the station fills need. */
|
|
374
1110
|
.ig-legend {
|
|
1111
|
+
align-items: center;
|
|
1112
|
+
background: var(--ig-surface-2);
|
|
375
1113
|
border: 0;
|
|
1114
|
+
border-top: var(--ig-stroke) solid var(--ig-line);
|
|
376
1115
|
display: flex;
|
|
377
1116
|
flex-wrap: wrap;
|
|
378
|
-
gap: var(--ig-space);
|
|
379
|
-
margin: 0
|
|
380
|
-
padding:
|
|
1117
|
+
gap: var(--ig-space-wide);
|
|
1118
|
+
margin: 0;
|
|
1119
|
+
padding: var(--ig-space) var(--ig-space-wide);
|
|
381
1120
|
}
|
|
382
1121
|
|
|
383
1122
|
.ig-legend-caption {
|
|
384
1123
|
color: var(--ig-text-muted);
|
|
385
|
-
font-
|
|
1124
|
+
font-family: var(--ig-font-mono);
|
|
1125
|
+
font-size: var(--ig-font-size-pill);
|
|
1126
|
+
letter-spacing: var(--ig-tracking-group);
|
|
386
1127
|
padding: 0;
|
|
1128
|
+
text-transform: uppercase;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
.ig-legend-item {
|
|
1132
|
+
align-items: center;
|
|
1133
|
+
color: var(--ig-text-body);
|
|
1134
|
+
display: inline-flex;
|
|
1135
|
+
font-family: var(--ig-font-mono);
|
|
1136
|
+
font-size: var(--ig-font-size-meta);
|
|
1137
|
+
gap: var(--ig-space-tight);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
.ig-legend-keys {
|
|
1141
|
+
display: inline-flex;
|
|
1142
|
+
gap: var(--ig-space-loose);
|
|
1143
|
+
margin-inline-start: auto;
|
|
387
1144
|
}
|
|
388
1145
|
`;
|
|
389
1146
|
//# sourceMappingURL=styles.js.map
|