@issuegraph/editor 0.10.0 → 0.22.1
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 +38 -7
- package/dist/a11y/baseline.d.ts.map +1 -1
- package/dist/a11y/baseline.js +4 -0
- package/dist/a11y/baseline.js.map +1 -1
- package/dist/audit/findings.d.ts +107 -1
- package/dist/audit/findings.d.ts.map +1 -1
- package/dist/audit/findings.js +113 -6
- package/dist/audit/findings.js.map +1 -1
- package/dist/audit/panel.d.ts +277 -0
- package/dist/audit/panel.d.ts.map +1 -0
- package/dist/audit/panel.js +462 -0
- package/dist/audit/panel.js.map +1 -0
- package/dist/audit/refused.d.ts +99 -0
- package/dist/audit/refused.d.ts.map +1 -0
- package/dist/audit/refused.js +276 -0
- package/dist/audit/refused.js.map +1 -0
- package/dist/audit/styles.d.ts +1 -1
- package/dist/audit/styles.d.ts.map +1 -1
- package/dist/audit/styles.js +428 -0
- package/dist/audit/styles.js.map +1 -1
- package/dist/audit/surface.d.ts +54 -12
- package/dist/audit/surface.d.ts.map +1 -1
- package/dist/audit/surface.js +53 -13
- package/dist/audit/surface.js.map +1 -1
- package/dist/create/draft.d.ts +19 -0
- package/dist/create/draft.d.ts.map +1 -1
- package/dist/create/draft.js +21 -0
- package/dist/create/draft.js.map +1 -1
- package/dist/create/keys.d.ts +68 -8
- package/dist/create/keys.d.ts.map +1 -1
- package/dist/create/keys.js +43 -5
- package/dist/create/keys.js.map +1 -1
- package/dist/index.d.ts +38 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -13
- package/dist/index.js.map +1 -1
- package/dist/overlay/render.d.ts +11 -3
- package/dist/overlay/render.d.ts.map +1 -1
- package/dist/overlay/render.js +22 -6
- package/dist/overlay/render.js.map +1 -1
- package/dist/overlay/request.d.ts +71 -0
- package/dist/overlay/request.d.ts.map +1 -0
- package/dist/overlay/request.js +129 -0
- package/dist/overlay/request.js.map +1 -0
- package/dist/overlay/styles.d.ts +1 -1
- package/dist/overlay/styles.d.ts.map +1 -1
- package/dist/overlay/styles.js +38 -7
- package/dist/overlay/styles.js.map +1 -1
- package/dist/reevaluate/parts.d.ts +130 -0
- package/dist/reevaluate/parts.d.ts.map +1 -0
- package/dist/reevaluate/parts.js +260 -0
- package/dist/reevaluate/parts.js.map +1 -0
- package/dist/reevaluate/render.d.ts +18 -11
- package/dist/reevaluate/render.d.ts.map +1 -1
- package/dist/reevaluate/render.js +21 -135
- package/dist/reevaluate/render.js.map +1 -1
- package/dist/reevaluate/styles.d.ts +1 -1
- package/dist/reevaluate/styles.d.ts.map +1 -1
- package/dist/reevaluate/styles.js +26 -0
- package/dist/reevaluate/styles.js.map +1 -1
- package/dist/reevaluate/view.d.ts +16 -1
- package/dist/reevaluate/view.d.ts.map +1 -1
- package/dist/reevaluate/view.js +21 -1
- package/dist/reevaluate/view.js.map +1 -1
- package/dist/reevaluate/words.d.ts +7 -0
- package/dist/reevaluate/words.d.ts.map +1 -1
- package/dist/scale/ladder.d.ts +62 -6
- package/dist/scale/ladder.d.ts.map +1 -1
- package/dist/scale/ladder.js +119 -8
- package/dist/scale/ladder.js.map +1 -1
- package/dist/scale/render.d.ts +44 -0
- package/dist/scale/render.d.ts.map +1 -1
- package/dist/scale/render.js +197 -27
- package/dist/scale/render.js.map +1 -1
- package/dist/scale/styles.d.ts +11 -5
- package/dist/scale/styles.d.ts.map +1 -1
- package/dist/scale/styles.js +133 -4
- package/dist/scale/styles.js.map +1 -1
- package/dist/workspace/host.d.ts +83 -1
- package/dist/workspace/host.d.ts.map +1 -1
- package/dist/workspace/host.js +197 -4
- package/dist/workspace/host.js.map +1 -1
- package/dist/workspace/inspector.d.ts +33 -7
- package/dist/workspace/inspector.d.ts.map +1 -1
- package/dist/workspace/inspector.js +15 -0
- package/dist/workspace/inspector.js.map +1 -1
- package/dist/workspace/mount.d.ts +23 -1
- package/dist/workspace/mount.d.ts.map +1 -1
- package/dist/workspace/mount.js +500 -17
- package/dist/workspace/mount.js.map +1 -1
- package/dist/workspace/rail.d.ts +5 -2
- package/dist/workspace/rail.d.ts.map +1 -1
- package/dist/workspace/rail.js.map +1 -1
- package/dist/workspace/render.d.ts +379 -3
- package/dist/workspace/render.d.ts.map +1 -1
- package/dist/workspace/render.js +893 -133
- package/dist/workspace/render.js.map +1 -1
- package/dist/workspace/selection.d.ts +11 -0
- package/dist/workspace/selection.d.ts.map +1 -1
- package/dist/workspace/selection.js +10 -0
- package/dist/workspace/selection.js.map +1 -1
- package/dist/workspace/styles.d.ts +1 -1
- package/dist/workspace/styles.d.ts.map +1 -1
- package/dist/workspace/styles.js +868 -18
- package/dist/workspace/styles.js.map +1 -1
- package/package.json +3 -3
package/dist/workspace/styles.js
CHANGED
|
@@ -58,7 +58,17 @@ export const workspaceStylesheet = `
|
|
|
58
58
|
squeeze the canvas, which is the one thing fixed positions exist to stop.
|
|
59
59
|
Nothing failed loudly, because an invalid declaration is simply absent.
|
|
60
60
|
|
|
61
|
-
40 is a reading measure for a title plus its id, in characters.
|
|
61
|
+
40 is a reading measure for a title plus its id, in characters.
|
|
62
|
+
|
|
63
|
+
THIS IS THE PRE-17k FALLBACK, and it is deliberately the OLD equal measure. 17k
|
|
64
|
+
gives 390 / 1fr / 330 for widths at or above 1360 and something else
|
|
65
|
+
entirely below it: the inspector lifts to an overlay from 1120, and under
|
|
66
|
+
that the canvas collapses to a strip. Neither of those exists yet, so
|
|
67
|
+
applying the wide proportions at every width squeezes the canvas instead
|
|
68
|
+
of collapsing it — measured at 990px, where the canvas fell to 248px. That
|
|
69
|
+
is the one rule 17k states outright inverted: "the rail never yields, the
|
|
70
|
+
canvas yields first." Below the breakpoint the old equal tracks are the
|
|
71
|
+
honest placeholder. */
|
|
62
72
|
grid-template-columns:
|
|
63
73
|
calc(var(--ig-char-width) * 40)
|
|
64
74
|
1fr
|
|
@@ -72,6 +82,53 @@ export const workspaceStylesheet = `
|
|
|
72
82
|
line-height: var(--ig-line-height);
|
|
73
83
|
}
|
|
74
84
|
|
|
85
|
+
/* THE CONTAINER IS THE MOUNT, NOT THE WORKSPACE, AND THAT IS NOT A DETAIL.
|
|
86
|
+
A container query CANNOT style the element that establishes the container:
|
|
87
|
+
put container-type on .ig-workspace and a rule inside @container matching
|
|
88
|
+
.ig-workspace never fires. It looked right, built clean, and did nothing —
|
|
89
|
+
measured at 1500px, where the rail and inspector sat at 312/312 while only
|
|
90
|
+
the canvas 1fr grew. A rule that can never fire is the same class as a guard
|
|
91
|
+
that can never fail, and the only reason this was caught is that the check
|
|
92
|
+
compared the TRACKS either side of the breakpoint rather than asking whether
|
|
93
|
+
the layout "changed".
|
|
94
|
+
|
|
95
|
+
.ig-mount is this package's own wrapper around the workspace, so the query
|
|
96
|
+
has a box to measure that is not the box it restyles. */
|
|
97
|
+
.ig-mount {
|
|
98
|
+
container-name: ig-workspace;
|
|
99
|
+
container-type: inline-size;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* 17k's WIDE LAYOUT, AT THE WIDTH 17k GIVES IT FOR. A container query, not a
|
|
103
|
+
viewport one, for the reason layer 1's row already answers to: the workspace
|
|
104
|
+
is a box a host places, and a package that reads the window cannot be
|
|
105
|
+
dropped into someone else's page.
|
|
106
|
+
|
|
107
|
+
1360 IS 17k's OWN NUMBER, not a chosen one — the table's first row reads
|
|
108
|
+
"at or above 1360: 390 / 1fr / 330, three zones, as 17a".
|
|
109
|
+
|
|
110
|
+
THE TWO ZONES ARE NOT THE SAME WIDTH, AND THAT IS THE POINT OF THIS RULE.
|
|
111
|
+
Both tracks were 40 characters, which is one reading measure applied twice;
|
|
112
|
+
17a draws 1292 = 390 + 572 + 330, a rail WIDER than the inspector. The rail
|
|
113
|
+
carries a rank, a title, a meta line and a delta chip on one row while the
|
|
114
|
+
inspector carries a column of stacked blocks — not the same problem, and
|
|
115
|
+
sizing them alike shortchanged the surface 17k says must never yield.
|
|
116
|
+
|
|
117
|
+
50 AND 42 CHARACTERS, NOT 390px AND 330px, because this file sizes zones in
|
|
118
|
+
TYPE on purpose: a host that scales its type scales the zones with it, and a
|
|
119
|
+
fixed track would not. At the shipped --ig-char-width of 7.8 that is 390 and
|
|
120
|
+
327.6 — the rail exact, the inspector 2.4px under 17k's figure. Stated
|
|
121
|
+
rather than rounded away; the type-relative property is worth more than the
|
|
122
|
+
2.4px, and it is the same BYO argument layer 1's row query rests on. */
|
|
123
|
+
@container ig-workspace (width >= 1360px) {
|
|
124
|
+
.ig-workspace {
|
|
125
|
+
grid-template-columns:
|
|
126
|
+
calc(var(--ig-char-width) * 50)
|
|
127
|
+
1fr
|
|
128
|
+
calc(var(--ig-char-width) * 42);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
75
132
|
.ig-zone {
|
|
76
133
|
min-width: 0;
|
|
77
134
|
/* Without this a long title in any zone sets that track's minimum width and
|
|
@@ -106,6 +163,46 @@ export const workspaceStylesheet = `
|
|
|
106
163
|
font-family: var(--ig-font-mono);
|
|
107
164
|
}
|
|
108
165
|
|
|
166
|
+
/* The adoption pair and the freshness stamp, hoisted out of layer 1's panel
|
|
167
|
+
header by #135. Quiet, because the row's only loud element is the entry at
|
|
168
|
+
its far end -- these are orientation, read once and then ignored. */
|
|
169
|
+
.ig-workspace-counts,
|
|
170
|
+
.ig-workspace-freshness {
|
|
171
|
+
color: var(--ig-text-muted);
|
|
172
|
+
font-family: var(--ig-font-ui);
|
|
173
|
+
font-size: var(--ig-font-size-small);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* THE ONLY TREATMENT STALENESS GETS, and it is why the stamp carries no word
|
|
177
|
+
for it: the state is on the element, so the sheet says what a stale read
|
|
178
|
+
looks like and no host has to translate an adjective. */
|
|
179
|
+
.ig-workspace-freshness[data-stale='true'] {
|
|
180
|
+
color: var(--ig-state-invalid);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* A CONTROL, NOT A CHIP. It sits inside the stamp because that is what it
|
|
184
|
+
refreshes, and it takes the button reset the sheet gives every other quiet
|
|
185
|
+
control on this surface rather than the accent the first-pass entry spends. */
|
|
186
|
+
.ig-workspace-refresh {
|
|
187
|
+
margin-left: var(--ig-space-tight);
|
|
188
|
+
font: inherit;
|
|
189
|
+
color: var(--ig-text);
|
|
190
|
+
background: var(--ig-surface-2);
|
|
191
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
192
|
+
border-radius: var(--ig-radius);
|
|
193
|
+
padding: 0 var(--ig-space-tight);
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.ig-workspace-refresh:hover {
|
|
198
|
+
border-color: var(--ig-accent);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.ig-workspace-refresh:focus-visible {
|
|
202
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
203
|
+
outline-offset: var(--ig-space-tight);
|
|
204
|
+
}
|
|
205
|
+
|
|
109
206
|
/* The one place the accent is spent on this surface, on the only action that
|
|
110
207
|
starts something. The frame draws it as the header's primary control. */
|
|
111
208
|
.ig-workspace-firstpass {
|
|
@@ -127,17 +224,315 @@ export const workspaceStylesheet = `
|
|
|
127
224
|
border-right: var(--ig-stroke) solid var(--ig-line);
|
|
128
225
|
}
|
|
129
226
|
|
|
227
|
+
/* §17a'S RAIL FOOTER, AND IT IS THE ZONE'S LAST ROW. The frame ends the rail
|
|
228
|
+
with it; that it is PINNED is this sheet's decision, on the reasoning §17c
|
|
229
|
+
already settled one zone over — the rail is the scroller, mount.ts restores
|
|
230
|
+
its scrollTop on every redraw, and a fact placed in the scrolled content is a
|
|
231
|
+
fact you have to go back for. .ig-canvas-toolbar below pins itself against
|
|
232
|
+
the other edge for exactly this reason and is the shape copied here.
|
|
233
|
+
|
|
234
|
+
IT ANCHORS ON A SHORT RAIL TOO, WITH NO FLEX LAYOUT, and this is recorded
|
|
235
|
+
because it looks as though it should not. A sticky box is offset within its
|
|
236
|
+
CONTAINING BLOCK to stay in the scrollport, and this zone's containing block
|
|
237
|
+
is the grid area — the full track height — not the height of the rows inside
|
|
238
|
+
it. So content shorter than the track still leaves the footer against the
|
|
239
|
+
bottom edge. Measured: rows 416px in a 445px track, footer flush, no flex
|
|
240
|
+
rule present. A review round proposed a column wrapper with an expanding row
|
|
241
|
+
to "push the footer down"; it was built, measured against this, changed
|
|
242
|
+
nothing, and was removed.
|
|
243
|
+
|
|
244
|
+
OPAQUE, BECAUSE IT OCCLUDES. Rows slide under it, so a transparent ground
|
|
245
|
+
would show the order through the count. That is also why the OPEN LIST IS NOT
|
|
246
|
+
IN HERE: an element taller than its scrollport cannot stick — the browser
|
|
247
|
+
clamps it and it scrolls like any other block — so a footer holding 248
|
|
248
|
+
entries loses the pin exactly when it grows, and covers the whole rail on the
|
|
249
|
+
way. The deeper reason is the rail's VIRTUALIZATION: railRowAt maps a scroll
|
|
250
|
+
offset to a row by floor((scrollTop - chrome) / pitch), so content of
|
|
251
|
+
arbitrary height anywhere in this track makes every offset below it name the
|
|
252
|
+
wrong row. The list is drawn in the canvas zone, which has no such
|
|
253
|
+
arithmetic. */
|
|
254
|
+
.ig-rail-footer {
|
|
255
|
+
position: sticky;
|
|
256
|
+
bottom: 0;
|
|
257
|
+
z-index: 1;
|
|
258
|
+
display: flex;
|
|
259
|
+
align-items: center;
|
|
260
|
+
justify-content: space-between;
|
|
261
|
+
gap: var(--ig-space-tight);
|
|
262
|
+
padding: var(--ig-space-tight) var(--ig-space);
|
|
263
|
+
border-top: var(--ig-stroke) solid var(--ig-line);
|
|
264
|
+
background: var(--ig-bg);
|
|
265
|
+
font-family: var(--ig-font-mono);
|
|
266
|
+
font-size: var(--ig-font-size-small);
|
|
267
|
+
line-height: var(--ig-line-height);
|
|
268
|
+
color: var(--ig-text-body);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.ig-rail-count {
|
|
272
|
+
color: var(--ig-text);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.ig-rail-isolated-toggle {
|
|
276
|
+
font: inherit;
|
|
277
|
+
color: var(--ig-accent);
|
|
278
|
+
background: none;
|
|
279
|
+
border: none;
|
|
280
|
+
padding: 0;
|
|
281
|
+
cursor: pointer;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.ig-rail-isolated-toggle:focus-visible {
|
|
285
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
286
|
+
outline-offset: var(--ig-space-tight);
|
|
287
|
+
}
|
|
288
|
+
|
|
130
289
|
.ig-zone[data-zone='canvas'] {
|
|
131
290
|
grid-area: canvas;
|
|
132
291
|
overflow: auto;
|
|
292
|
+
/* THE OVERLAY'S CONTAINING BLOCK. §17d's panel is positioned against THIS
|
|
293
|
+
zone rather than the workspace, and that is what keeps it off the rail
|
|
294
|
+
without a magic offset: the rail is a different grid area, so an absolutely
|
|
295
|
+
positioned child of the canvas cannot reach it however wide it gets.
|
|
296
|
+
RULINGS.md §3 states the constraint and gives the reason — "judging a
|
|
297
|
+
finding is largely a question of what it would do to the order, so the
|
|
298
|
+
order has to stay readable while you judge." */
|
|
299
|
+
position: relative;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* §17f'S CAPTION, AND IT IS THE ZONE'S FIRST ROW. Frame 17a puts it above the
|
|
303
|
+
graph with a rule under it, which is the same shape the header row beside it
|
|
304
|
+
already has — so it takes that row's padding tokens rather than a bespoke
|
|
305
|
+
pair, and the two read as one band across the surface.
|
|
306
|
+
|
|
307
|
+
THE GROUND, NOT THE CARD COLOUR. --ig-surface is what a RAISED element takes
|
|
308
|
+
here: a bordered card, a button. This row is a full-bleed structural band, and
|
|
309
|
+
painting it the panel colour made it read as a card floating on the canvas —
|
|
310
|
+
which is also what the frame does not draw, and what the comment above it
|
|
311
|
+
claimed it was not. --ig-bg is the ground .ig-workspace itself paints and the
|
|
312
|
+
header row inherits, so the two really do match. It has to be OPAQUE either
|
|
313
|
+
way: the row is sticky over a scrolling graph and must occlude it.
|
|
314
|
+
|
|
315
|
+
IT DOES NOT SCROLL WITH THE CANVAS, deliberately. The zone scrolls (above),
|
|
316
|
+
and a caption saying "6 of 312 shown" that scrolls away is a caption you have
|
|
317
|
+
to go back for. A sticky position keeps it against the zone's top edge
|
|
318
|
+
without taking the graph out of the zone's own scroll. */
|
|
319
|
+
.ig-canvas-toolbar {
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: var(--ig-space-tight);
|
|
323
|
+
padding: var(--ig-space-tight) var(--ig-space);
|
|
324
|
+
border-bottom: var(--ig-stroke) solid var(--ig-line);
|
|
325
|
+
position: sticky;
|
|
326
|
+
top: 0;
|
|
327
|
+
background: var(--ig-bg);
|
|
328
|
+
z-index: 1;
|
|
133
329
|
}
|
|
134
330
|
|
|
331
|
+
/* MONO AND MUTED, because it is a read-out rather than a heading: the frame
|
|
332
|
+
sets it in the same mono face at the same muted hue as the rail's own footer
|
|
333
|
+
count, and the two are the same kind of fact. */
|
|
334
|
+
.ig-canvas-caption {
|
|
335
|
+
margin: 0;
|
|
336
|
+
font-family: var(--ig-font-mono);
|
|
337
|
+
font-size: var(--ig-font-size-micro);
|
|
338
|
+
color: var(--ig-text-muted);
|
|
339
|
+
min-width: 0;
|
|
340
|
+
overflow: hidden;
|
|
341
|
+
text-overflow: ellipsis;
|
|
342
|
+
white-space: nowrap;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* ITS OWN CLASS, NOT LAYER 1'S .ig-count. They look like the same thing and are
|
|
346
|
+
not: layer 1's is the isolated-issue tally that "sits directly on the panel,
|
|
347
|
+
outside the padded groups, so it carries the panel's own inset" — 12px 20px of
|
|
348
|
+
it. Borrowing the name put that inset around two numbers in the middle of a
|
|
349
|
+
sentence, which is what the frame comparison caught. */
|
|
350
|
+
.ig-canvas-count {
|
|
351
|
+
color: var(--ig-text-body);
|
|
352
|
+
font-variant-numeric: tabular-nums;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* THE CLAUSES DO NOT BREAK INTERNALLY. The caption is one line that ellipsizes
|
|
356
|
+
as a whole; what must not happen is a label parting from the key it names, or
|
|
357
|
+
a count parting from the word that says what it counts. */
|
|
358
|
+
.ig-canvas-focus,
|
|
359
|
+
.ig-canvas-shown {
|
|
360
|
+
white-space: nowrap;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* PUSHED RIGHT BY ITS OWN MARGIN, NOT BY THE ROW'S JUSTIFICATION. The row's
|
|
364
|
+
arity changes: off the direct tier the caption is gone and the pill is the
|
|
365
|
+
only child, and justify-content: space-between puts a lone item at main
|
|
366
|
+
START — so the pill jumped to the left edge on exactly the tiers a large
|
|
367
|
+
backlog is always in, which is the state this surface exists to handle well.
|
|
368
|
+
margin-left: auto is one declaration that is correct at either arity, and it
|
|
369
|
+
is also what leaves #181's projection toggle a real slot: a control added
|
|
370
|
+
ahead of the caption lands in the left group without touching this rule.
|
|
371
|
+
|
|
372
|
+
THE TINT PAIR, NOT A BARE OUTLINE. The tint fill and tint border tokens
|
|
373
|
+
exist for exactly this — "a fill of its own hue inside a heavier border of
|
|
374
|
+
the same hue" — and the frame draws the pill that way. Reaching for the
|
|
375
|
+
accent directly would give a solid chip that reads as loud as the selection.
|
|
376
|
+
|
|
377
|
+
IT NEVER SHRINKS. The caption beside it is the part that may ellipsize; the
|
|
378
|
+
pill is three or four characters and losing them would leave a coloured stub
|
|
379
|
+
saying nothing. */
|
|
380
|
+
.ig-edit-mode {
|
|
381
|
+
flex: 0 0 auto;
|
|
382
|
+
margin-left: auto;
|
|
383
|
+
font-family: var(--ig-font-mono);
|
|
384
|
+
font-size: var(--ig-font-size-pill);
|
|
385
|
+
letter-spacing: var(--ig-tracking-pill);
|
|
386
|
+
color: var(--ig-accent);
|
|
387
|
+
/* THE TINT TOKENS ARE PERCENTAGES, NOT COLOURS — 8% and 30% — so they are only
|
|
388
|
+
meaningful inside color-mix, which is how every other tinted badge in the
|
|
389
|
+
package consumes them. Handed straight to background and border-color they
|
|
390
|
+
are invalid, and an invalid declaration is DROPPED SILENTLY: the pill
|
|
391
|
+
rendered as bare cyan text with no fill and no border, and no test noticed
|
|
392
|
+
because nothing here was a hex literal. */
|
|
393
|
+
background: color-mix(in srgb, var(--ig-accent) var(--ig-tint-fill), transparent);
|
|
394
|
+
border: var(--ig-stroke) solid
|
|
395
|
+
color-mix(in srgb, var(--ig-accent) var(--ig-tint-border), transparent);
|
|
396
|
+
border-radius: var(--ig-radius-small);
|
|
397
|
+
padding: var(--ig-space-micro) var(--ig-space-snug);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* ONE SCROLL TRACK, AND EXACTLY ONE SIBLING IS BOUNDED INSIDE IT. This zone
|
|
401
|
+
holds three: §17d's AUDIT REGION, this column's selection detail, and the
|
|
402
|
+
.ig-chrome the mount appends. #177 settled how they share it, and the whole
|
|
403
|
+
of the answer is that the zone stays ONE track while the region alone takes a
|
|
404
|
+
declared share of it (max-height: 50%, scrolling itself past that).
|
|
405
|
+
.ig-inspector and .ig-chrome keep this track's own scrolling and declare no
|
|
406
|
+
share, so neither can be clipped by any height.
|
|
407
|
+
|
|
408
|
+
THE BOUNDED SIBLING IS A REGION NOW, AND THAT IS #177'S RULE KEPT RATHER THAN
|
|
409
|
+
RESTATED. §17d has two surfaces — the findings panel and, since the fourth
|
|
410
|
+
class moved out of it, the refused block (audit/refused.ts) — and bounding
|
|
411
|
+
each at half the column lets the two of them take ALL of it, which is worse
|
|
412
|
+
than the state #177 fixed rather than a smaller version of it. So
|
|
413
|
+
workspace/render.ts wraps both in .ig-audit-overlay and the share is declared
|
|
414
|
+
once, here, on the thing the zone actually holds. Neither leaf declares a
|
|
415
|
+
size of its own; audit/styles.ts says so at both.
|
|
416
|
+
|
|
417
|
+
AN EARLIER REVISION OF THIS COMMENT CREDITED audit/styles.ts WITH THE SHARE.
|
|
418
|
+
It never carried it — that file states in as many words that the panel
|
|
419
|
+
"DECLARES NO SIZE OF ITS OWN" — and the misattribution is why the fourth
|
|
420
|
+
sibling nearly arrived unbounded.
|
|
421
|
+
|
|
422
|
+
THAT IS A PROPERTY NOW, NOT A LUCKY DEFAULT, and it is what makes the chrome
|
|
423
|
+
safe. A TWO-PANE VERSION WAS TRIED AND REVERTED: making the zone a flex
|
|
424
|
+
column with overflow: hidden did give the audit and the selection independent
|
|
425
|
+
scroll — and it CLIPPED the mount's chrome, a third sibling holding the
|
|
426
|
+
target search's lower matches, the cancel button and the key legend, all of
|
|
427
|
+
which lost the scrolling the zone used to give them. The lesson was read as
|
|
428
|
+
"treat the chrome as a third pane"; it is better read as "do not make the
|
|
429
|
+
zone a multi-pane layout at all". Bounding one sibling needs no panes.
|
|
430
|
+
|
|
431
|
+
WHY THE PANEL IS THE ONE THAT IS BOUNDED. It is the only GLOBAL member of a
|
|
432
|
+
selection-scoped zone, and renderWorkspace draws it FIRST — so unbounded, it
|
|
433
|
+
is the one sibling whose length pushes a detail the reader just asked for
|
|
434
|
+
below the fold. The selection detail and the chrome are both about what the
|
|
435
|
+
reader is doing; the audit is about the document. §17a fixes the workspace at
|
|
436
|
+
three zones plus a header, so there is nowhere else ambient for it to be, and
|
|
437
|
+
a share is what makes it affordable where it has to live. */
|
|
135
438
|
.ig-zone[data-zone='inspector'] {
|
|
136
439
|
grid-area: inspector;
|
|
137
440
|
overflow-y: auto;
|
|
138
441
|
border-left: var(--ig-stroke) solid var(--ig-line);
|
|
139
442
|
}
|
|
140
443
|
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
/* THE REGION SCROLLS; ITS MEMBERS DO NOT SHRINK. Both leaves declare
|
|
447
|
+
min-height: 0 — correct for each of them, because each was once the scroll
|
|
448
|
+
container itself — and in a bounded flex column that is exactly the licence
|
|
449
|
+
to squeeze them below their content. Measured in a browser rather than
|
|
450
|
+
reasoned about: with a refusal and five findings the block was laid out 54px
|
|
451
|
+
tall around 131px of content, and since a leaf's own overflow is visible it
|
|
452
|
+
PAINTED OVER the panel underneath it. Nothing threw, no test failed, and the
|
|
453
|
+
markup was correct — the two surfaces were simply drawn on top of each other.
|
|
454
|
+
|
|
455
|
+
flex-shrink RATHER THAN A HEIGHT ON EITHER LEAF, which is the same layering
|
|
456
|
+
the share above follows: how the region's members divide it is a fact about
|
|
457
|
+
the region, and a leaf that sized itself here would be wrong in every other
|
|
458
|
+
composition. The region's own max-height is what bounds the pair; this is
|
|
459
|
+
what makes the overflow it declares actually reachable. */
|
|
460
|
+
.ig-zone[data-zone='canvas'] .ig-audit-overlay > * {
|
|
461
|
+
flex-shrink: 0;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
/* §17d'S PANEL, AS AN OVERLAY OVER THE CANVAS.
|
|
466
|
+
|
|
467
|
+
RULINGS.md §3: "a transient overlay anchored to the header count, floating
|
|
468
|
+
over the canvas, 520px wide, dismissed on Escape." It was a child of the
|
|
469
|
+
INSPECTOR zone until now, sharing that column's height with the selection —
|
|
470
|
+
§17a fixes three zones and none of them is the audit's, so it had nowhere to
|
|
471
|
+
go and took a share of the one next to it. At six findings the inspector was
|
|
472
|
+
pushed below the fold.
|
|
473
|
+
|
|
474
|
+
520px IS DESIGN'S NUMBER, not this package's, which is why it is written as
|
|
475
|
+
one rather than derived from a token. It is expressed in ch units against the
|
|
476
|
+
type scale so it survives a theme that changes the font size, and clamped to
|
|
477
|
+
the zone so a narrow canvas cannot push it over the rail — the constraint §3
|
|
478
|
+
states outright.
|
|
479
|
+
|
|
480
|
+
ANCHORED TOP-RIGHT, under the header count it belongs to. The count sits at
|
|
481
|
+
the right end of the header band, so the panel hangs from that corner and the
|
|
482
|
+
eye travels the shortest distance from the control to what it opened.
|
|
483
|
+
|
|
484
|
+
IT PAINTS OVER THE GRAPH, which is what an overlay is: z-index above the
|
|
485
|
+
canvas content, and its own raised surface and shadow so the graph beneath
|
|
486
|
+
reads as behind rather than as a background it is part of.
|
|
487
|
+
|
|
488
|
+
--ig-elevation-overlay IS THE TOKEN FOR EXACTLY THIS, and the first draft
|
|
489
|
+
wrote a literal rgb() instead. The package's own guard caught it, correctly:
|
|
490
|
+
the theme's two shadows are deliberately the only values carrying a colour,
|
|
491
|
+
so a host retheming owns them and a literal here would be invisible to that.
|
|
492
|
+
|
|
493
|
+
SCOPED TO THE ZONE, and every declaration is in this one rule. Two reasons,
|
|
494
|
+
and the second is the sheet's own standing rule: an absolutely positioned
|
|
495
|
+
.ig-audit-overlay outside this zone has no containing block to hang from and
|
|
496
|
+
would anchor to the page, and the panel is a public export a consumer can
|
|
497
|
+
render standalone. The same argument the inspector's old share rule made. */
|
|
498
|
+
/* BORDER-BOX, AND IT IS LOAD-BEARING. There IS a universal reset in this
|
|
499
|
+
codebase and it does not reach here: viewer/src/styles.ts scopes it to
|
|
500
|
+
.ig-viewer descendants, and this panel is a sibling of the rail's viewer
|
|
501
|
+
rather than inside it. Without it the cap is measured on the CONTENT box and
|
|
502
|
+
the panel's own padding and border push the drawn box past it. Nothing looks
|
|
503
|
+
broken.
|
|
504
|
+
|
|
505
|
+
THE PANEL SCROLLS, NOT THE LIST INSIDE IT. Scrolling the list would pin the
|
|
506
|
+
panel's head, which is the wrong trade twice over. The ambient count 17d
|
|
507
|
+
fixes is the WORKSPACE HEADER's, drawn in the header grid area and outside
|
|
508
|
+
this zone entirely - it already never moves, so a second pinned count buys
|
|
509
|
+
nothing. And the list has zero horizontal padding, so making it the scroll
|
|
510
|
+
container computes its overflow-x to auto and CLIPS the focus ring on every
|
|
511
|
+
card's control: an outline is ink overflow, so it is cut rather than
|
|
512
|
+
scrolled to. Each leaf's own padding gives those rings room. */
|
|
513
|
+
.ig-zone[data-zone='canvas'] .ig-audit-overlay {
|
|
514
|
+
box-sizing: border-box;
|
|
515
|
+
display: flex;
|
|
516
|
+
flex-direction: column;
|
|
517
|
+
min-height: 0;
|
|
518
|
+
overflow-y: auto;
|
|
519
|
+
position: absolute;
|
|
520
|
+
z-index: 3;
|
|
521
|
+
top: var(--ig-space-tight);
|
|
522
|
+
right: var(--ig-space-tight);
|
|
523
|
+
width: min(calc(var(--ig-char-width) * 66.67), calc(100% - var(--ig-space-tight) * 2));
|
|
524
|
+
max-height: calc(100% - var(--ig-space-tight) * 2);
|
|
525
|
+
/* --ig-surface IS THE RAISED ONE. The first draft wrote --ig-raised, which
|
|
526
|
+
does not exist; the sheet's own guard listed it as a property nothing
|
|
527
|
+
resolves, and an unresolved custom property is not an error in CSS — it
|
|
528
|
+
computes to nothing and the panel would have been transparent over the
|
|
529
|
+
graph. */
|
|
530
|
+
background: var(--ig-surface);
|
|
531
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
532
|
+
border-radius: var(--ig-radius);
|
|
533
|
+
box-shadow: var(--ig-elevation-overlay);
|
|
534
|
+
}
|
|
535
|
+
|
|
141
536
|
/* THE AMBIENT LEFT-BAR. A 2px gold rule on the affected row and nothing else —
|
|
142
537
|
no fill, no icon, no badge. §17a's whole ask is that encoding errors stay
|
|
143
538
|
visible while you work rather than pulling you out of it.
|
|
@@ -162,8 +557,12 @@ export const workspaceStylesheet = `
|
|
|
162
557
|
|
|
163
558
|
ONE TREATMENT FOR ALL FOUR SEVERITIES, which is also a correction. §17d
|
|
164
559
|
names exactly one ambient mark — "a 2px gold left-bar on the affected rail
|
|
165
|
-
row" — and puts the severity distinction in the findings list, which
|
|
166
|
-
|
|
560
|
+
row" — and puts the severity distinction in the findings list, which
|
|
561
|
+
audit/panel.ts now draws. (It read "which is host-side" until that panel
|
|
562
|
+
existed; the reasoning is unaffected — the distinction still belongs to the
|
|
563
|
+
list rather than to this bar — but the list is the package's now.)
|
|
564
|
+
|
|
565
|
+
The misleading variant this replaces gave the LEAST urgent
|
|
167
566
|
severity ("clearing is bookkeeping, not urgency") the alarm colour while
|
|
168
567
|
every other finding got cyan, inverting the design it came from. */
|
|
169
568
|
.ig-zone[data-zone='rail'] [data-ig-audit] {
|
|
@@ -293,6 +692,16 @@ export const workspaceStylesheet = `
|
|
|
293
692
|
gap: var(--ig-space-tight);
|
|
294
693
|
}
|
|
295
694
|
|
|
695
|
+
/* §17a PUTS '+ add' ON THE HEADING'S ROW, opposite the heading. The list
|
|
696
|
+
between them is unbounded, so a control after it drifts down the panel as a
|
|
697
|
+
subject gains relationships; here its position does not depend on content. */
|
|
698
|
+
.ig-inspector-relationships-head {
|
|
699
|
+
display: flex;
|
|
700
|
+
align-items: baseline;
|
|
701
|
+
justify-content: space-between;
|
|
702
|
+
gap: var(--ig-space-tight);
|
|
703
|
+
}
|
|
704
|
+
|
|
296
705
|
/* SECTION 17a DRAWS EVERY INSPECTOR HEADING IN CAPS -- WHY RANK 2,
|
|
297
706
|
RELATIONSHIPS, ADD RELATIONSHIP -- so the treatment is shared rather than
|
|
298
707
|
spelled per heading. Tracking widens with the caps because letterforms at a
|
|
@@ -329,10 +738,17 @@ export const workspaceStylesheet = `
|
|
|
329
738
|
}
|
|
330
739
|
|
|
331
740
|
|
|
332
|
-
/* THE PANEL'S
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
741
|
+
/* THE PANEL'S TWO QUIET BUTTONS SHARE ONE TREATMENT — clear and cancel. They
|
|
742
|
+
are the same affordance at two moments (leave this selection, abandon the
|
|
743
|
+
draft) and drawing them two ways would invent a hierarchy the design does
|
|
744
|
+
not state.
|
|
745
|
+
|
|
746
|
+
'+ add' WAS THE THIRD AND HAS LEFT THE SET, because frame 17a moved it and
|
|
747
|
+
redrew it: on the relationships header row it is unbordered accent text with
|
|
748
|
+
the key beside it, not a filled box. That is a hierarchy the design DOES
|
|
749
|
+
state — a header affordance reads differently from a control in the panel
|
|
750
|
+
body — so matching it here is following the frame rather than inventing a
|
|
751
|
+
difference. Its focus ring is still shared, below. The destructive controls are
|
|
336
752
|
deliberately NOT in this set: a row's '✕' is a glyph in the row's own slot,
|
|
337
753
|
and the mount's delete button carries its own danger treatment.
|
|
338
754
|
|
|
@@ -344,7 +760,6 @@ export const workspaceStylesheet = `
|
|
|
344
760
|
baseline that rule's own comment says it is there to get. Declared where each
|
|
345
761
|
is true instead. */
|
|
346
762
|
.ig-inspector-clear,
|
|
347
|
-
.ig-inspector-addbutton,
|
|
348
763
|
.ig-inspector-cancel {
|
|
349
764
|
background: var(--ig-surface-2);
|
|
350
765
|
color: var(--ig-text-body);
|
|
@@ -359,10 +774,42 @@ export const workspaceStylesheet = `
|
|
|
359
774
|
.ig-inspector-clear:focus-visible,
|
|
360
775
|
.ig-inspector-addbutton:focus-visible,
|
|
361
776
|
.ig-inspector-cancel:focus-visible {
|
|
777
|
+
/* '+ add' keeps the shared focus ring though it left the shared fill: a
|
|
778
|
+
focus indicator is an accessibility guarantee, not a visual register. */
|
|
362
779
|
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
363
780
|
outline-offset: var(--ig-space-tight);
|
|
364
781
|
}
|
|
365
782
|
|
|
783
|
+
/* §17a's '+ add', AS THE FRAME DRAWS IT: accent text on the header row, no box.
|
|
784
|
+
It is a header affordance rather than a control in the panel body, and the
|
|
785
|
+
frame states that difference by removing the border and the fill rather than
|
|
786
|
+
by moving it alone. */
|
|
787
|
+
.ig-inspector-addbutton {
|
|
788
|
+
display: inline-flex;
|
|
789
|
+
align-items: baseline;
|
|
790
|
+
gap: var(--ig-space-micro);
|
|
791
|
+
background: none;
|
|
792
|
+
border: none;
|
|
793
|
+
border-radius: var(--ig-radius);
|
|
794
|
+
padding: 0;
|
|
795
|
+
color: var(--ig-accent);
|
|
796
|
+
font-family: var(--ig-font-ui);
|
|
797
|
+
font-size: var(--ig-font-size-small);
|
|
798
|
+
cursor: pointer;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/* THE KEY, QUIETER THAN THE ACT IT NAMES. It is a hint about how to reach the
|
|
802
|
+
control, not part of the control's label, so it takes the muted tone the
|
|
803
|
+
panel gives every line that states a fact rather than offering an act.
|
|
804
|
+
UPPERCASED HERE, NEVER IN THE MARKUP: the binding table stores the lowercase
|
|
805
|
+
key a press normalizes to, and drawing 'R' is presentation. A second,
|
|
806
|
+
uppercase copy in the package would be the drift RELATE_KEY exists to end. */
|
|
807
|
+
.ig-inspector-addkey {
|
|
808
|
+
color: var(--ig-text-muted);
|
|
809
|
+
font-family: var(--ig-font-mono);
|
|
810
|
+
text-transform: uppercase;
|
|
811
|
+
}
|
|
812
|
+
|
|
366
813
|
.ig-relationship-list {
|
|
367
814
|
list-style: none;
|
|
368
815
|
margin: 0;
|
|
@@ -605,18 +1052,30 @@ export const workspaceStylesheet = `
|
|
|
605
1052
|
border-style: dotted;
|
|
606
1053
|
}
|
|
607
1054
|
|
|
608
|
-
/* THE
|
|
609
|
-
|
|
610
|
-
|
|
1055
|
+
/* THE KIND STEP'S OWN BOX — the heading, the numbered list and the cancel that
|
|
1056
|
+
withdraws from it.
|
|
1057
|
+
|
|
1058
|
+
IT NO LONGER HOLDS '+ add'. This box was once "one place the reader returns
|
|
1059
|
+
to", holding whichever of the two create steps was live; frame 17a splits
|
|
1060
|
+
them by zone, putting '+ add' on the relationships header row and leaving the
|
|
1061
|
+
kinds here under a heading of their own. The two steps are still exclusive —
|
|
1062
|
+
'createStep' answers one of them — but they are no longer drawn in one
|
|
1063
|
+
place, so this rule is about the kind step alone. */
|
|
611
1064
|
.ig-inspector-add {
|
|
612
1065
|
display: flex;
|
|
613
1066
|
flex-direction: column;
|
|
614
1067
|
gap: var(--ig-space-tight);
|
|
615
1068
|
}
|
|
616
1069
|
|
|
617
|
-
/* Sized by
|
|
618
|
-
quiet-button rule above, which deliberately does not carry this.
|
|
619
|
-
|
|
1070
|
+
/* Sized by its own word rather than stretched across the column — see the
|
|
1071
|
+
quiet-button rule above, which deliberately does not carry this.
|
|
1072
|
+
|
|
1073
|
+
'+ add' IS NO LONGER LISTED HERE, and dropping it was required rather than
|
|
1074
|
+
tidy. This declaration is scoped to '.ig-inspector-add', a COLUMN; '+ add'
|
|
1075
|
+
now sits in the relationships header, a ROW, where 'align-self' beats the
|
|
1076
|
+
container's 'align-items' and would top-align the control against the
|
|
1077
|
+
heading — the exact bug the '.ig-inspector-clear' comment above records
|
|
1078
|
+
having already been fixed once. */
|
|
620
1079
|
.ig-inspector-cancel {
|
|
621
1080
|
align-self: flex-start;
|
|
622
1081
|
}
|
|
@@ -641,14 +1100,25 @@ export const workspaceStylesheet = `
|
|
|
641
1100
|
gap: var(--ig-space-micro);
|
|
642
1101
|
}
|
|
643
1102
|
|
|
644
|
-
/* Full width, so the whole entry is the hit target
|
|
645
|
-
|
|
646
|
-
|
|
1103
|
+
/* Full width, so the whole entry is the hit target.
|
|
1104
|
+
|
|
1105
|
+
THE DIGIT IS A CHIP AT THE ROW'S END, which is frame 17a's device and
|
|
1106
|
+
REVERSES the placement #144 shipped. That decision was made in the same §17a
|
|
1107
|
+
pass and with this frame available, so it is overturned on the merits rather
|
|
1108
|
+
than as an oversight: what made the old left-hand column read as a set of
|
|
1109
|
+
KEYS was vertical alignment, which a label long enough to wrap breaks, while
|
|
1110
|
+
a bordered chip carries the key-cap signal on each row by itself and cannot
|
|
1111
|
+
come apart. Reversing a same-campaign decision is called out on the pull
|
|
1112
|
+
request so autnmy/issuegraph#147 rules rather than the implementer.
|
|
1113
|
+
|
|
1114
|
+
CENTRED, NOT BASELINE-ALIGNED. A chip has its own border and padding, so on a
|
|
1115
|
+
baseline it sits low against the glyph and the label; the frame's row centres
|
|
1116
|
+
all three. */
|
|
647
1117
|
.ig-kind-option {
|
|
648
1118
|
width: 100%;
|
|
649
1119
|
display: flex;
|
|
650
1120
|
gap: var(--ig-space-tight);
|
|
651
|
-
align-items:
|
|
1121
|
+
align-items: center;
|
|
652
1122
|
background: var(--ig-surface);
|
|
653
1123
|
color: var(--ig-text-body);
|
|
654
1124
|
border: var(--ig-stroke) solid var(--ig-line);
|
|
@@ -665,7 +1135,18 @@ export const workspaceStylesheet = `
|
|
|
665
1135
|
outline-offset: var(--ig-space-tight);
|
|
666
1136
|
}
|
|
667
1137
|
|
|
1138
|
+
/* THE CHIP TAKES THE SLACK BEFORE IT, rather than the label being told to grow.
|
|
1139
|
+
The label is drawn by layer 1's shared 'glyphAndLabel' and carries no class of
|
|
1140
|
+
its own, so selecting it from here means selecting by exclusion — a rule that
|
|
1141
|
+
silently stops matching the day that helper adds an element. An auto margin
|
|
1142
|
+
is stated on the element this rule already owns, needs nothing of the label,
|
|
1143
|
+
and puts the chip at the row's end whatever precedes it. */
|
|
668
1144
|
.ig-kind-digit {
|
|
1145
|
+
flex: 0 0 auto;
|
|
1146
|
+
margin-left: auto;
|
|
1147
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
1148
|
+
border-radius: var(--ig-radius);
|
|
1149
|
+
padding: 0 var(--ig-space-micro);
|
|
669
1150
|
font-family: var(--ig-font-mono);
|
|
670
1151
|
color: var(--ig-text-muted);
|
|
671
1152
|
}
|
|
@@ -842,5 +1323,374 @@ export const workspaceStylesheet = `
|
|
|
842
1323
|
font-size: var(--ig-font-size-small);
|
|
843
1324
|
color: var(--ig-text-muted);
|
|
844
1325
|
}
|
|
1326
|
+
|
|
1327
|
+
/* §17c ON THE ROW: the tint, the third column, and the chip in place.
|
|
1328
|
+
|
|
1329
|
+
THE TINT IS DRAWN FROM AN ATTRIBUTE rather than from a class the row is
|
|
1330
|
+
given, which is audit/surface.ts's precedent and its reason: layer 1 owns
|
|
1331
|
+
the row's markup, so layer 2 says WHICH KIND and the stylesheet says what
|
|
1332
|
+
that kind looks like. A row the edit did not touch carries no attribute at
|
|
1333
|
+
all, so none of these rules can reach it, and "unaffected rows are left
|
|
1334
|
+
completely alone" is structural rather than asserted.
|
|
1335
|
+
|
|
1336
|
+
THESE REACH LAYER 1'S OWN CLASSES, and that is a deliberate exception of
|
|
1337
|
+
exactly the shape reevaluate/styles.ts already declares for the greyed rail:
|
|
1338
|
+
only from INSIDE this surface's own root, and only for a state layer 1 does
|
|
1339
|
+
not model. The viewer draws a row; whether the last edit moved that row is a
|
|
1340
|
+
fact only the store knows, so the mark belongs to whoever knows it.
|
|
1341
|
+
|
|
1342
|
+
BOTH ROW SHAPES, because a delta can land on either. A ranked row is an
|
|
1343
|
+
.ig-slot; an excluded one — the shape an issue takes when an edit turns it
|
|
1344
|
+
into a duplicate — is an .ig-footer-row, and it is still navigable, so
|
|
1345
|
+
reevaluateView still places its chip. An earlier revision listed .ig-slot
|
|
1346
|
+
only, so a left row got its chip and its extended name and no ground.
|
|
1347
|
+
|
|
1348
|
+
EVERY VALUE deltaKind CAN EMIT, and that list is readiness, then a
|
|
1349
|
+
movement's direction, then a presence: promoted, newly-held, up, down,
|
|
1350
|
+
entered, left. An earlier revision keyed a rule on 'absent', which is not a
|
|
1351
|
+
value this code has ever produced — presence is 'entered' | 'left' — so that
|
|
1352
|
+
rule matched nothing while looking like the neutral case, and a left row
|
|
1353
|
+
took the READY tint from the bare fallback below. Named exhaustively now
|
|
1354
|
+
rather than defaulted, so a seventh value renders untinted rather than
|
|
1355
|
+
wrong.
|
|
1356
|
+
|
|
1357
|
+
BACKGROUND-COLOR, NEVER THE SHORTHAND. the background shorthand resets background-image
|
|
1358
|
+
to none, and layer 1 draws the HELD row's hatch as a repeating-linear-
|
|
1359
|
+
gradient on exactly that property. These rules are more specific and load
|
|
1360
|
+
after it, so the shorthand silently took the hatch off any row that was both
|
|
1361
|
+
held and changed — which is not a corner: newly-held is the delta that
|
|
1362
|
+
co-occurs with data-held='true' by definition, so the most common overlap
|
|
1363
|
+
lost the held channel entirely. The longhand leaves the gradient alone.
|
|
1364
|
+
|
|
1365
|
+
COLOUR-MIX ON THE TOKEN THE KIND ALREADY NAMES, at the strength layer 1
|
|
1366
|
+
tints its own rows with. Inventing --ig-row-promoted would put a hue in this
|
|
1367
|
+
package that a host retheming the station colours could not move in step,
|
|
1368
|
+
and inventing a percentage would make this tint drift from the unit tint
|
|
1369
|
+
layer 1 draws with --ig-tint-unit. */
|
|
1370
|
+
.ig-workspace .ig-slot[data-ig-delta='promoted'],
|
|
1371
|
+
.ig-workspace .ig-slot[data-ig-delta='up'],
|
|
1372
|
+
.ig-workspace .ig-slot[data-ig-delta='entered'],
|
|
1373
|
+
.ig-workspace .ig-footer-row[data-ig-delta='promoted'],
|
|
1374
|
+
.ig-workspace .ig-footer-row[data-ig-delta='up'],
|
|
1375
|
+
.ig-workspace .ig-footer-row[data-ig-delta='entered'] {
|
|
1376
|
+
background-color: color-mix(in srgb, var(--ig-station-ready) var(--ig-tint-unit), transparent);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
.ig-workspace .ig-slot[data-ig-delta='newly-held'],
|
|
1380
|
+
.ig-workspace .ig-slot[data-ig-delta='down'],
|
|
1381
|
+
.ig-workspace .ig-footer-row[data-ig-delta='newly-held'],
|
|
1382
|
+
.ig-workspace .ig-footer-row[data-ig-delta='down'] {
|
|
1383
|
+
background-color: color-mix(in srgb, var(--ig-station-held) var(--ig-tint-unit), transparent);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
/* A row the edit took OUT of the order. Neutral rather than held: it is not
|
|
1387
|
+
waiting on anything, it is simply no longer ranked. */
|
|
1388
|
+
.ig-workspace .ig-slot[data-ig-delta='left'],
|
|
1389
|
+
.ig-workspace .ig-footer-row[data-ig-delta='left'] {
|
|
1390
|
+
background-color: color-mix(in srgb, var(--ig-text-muted) var(--ig-tint-unit), transparent);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/* THE THIRD COLUMN IS WHAT PUTS THE CHIP AT THE ROW'S TRAILING EDGE.
|
|
1394
|
+
|
|
1395
|
+
The frame draws the row as rank, body, chip — three columns, the last
|
|
1396
|
+
sized to its content. Layer 1's own rule is a TWO-column grid, so a chip
|
|
1397
|
+
appended as a third child wrapped onto an implicit second row and sat under
|
|
1398
|
+
the rank. That was visible in the first capture of this pair, and it is why
|
|
1399
|
+
this rule is a column template rather than a margin: in a grid, an auto
|
|
1400
|
+
inline margin cannot move an item that is in the wrong row to begin with.
|
|
1401
|
+
|
|
1402
|
+
ONLY ON A ROW THAT HAS A CHIP, so a row with no delta keeps layer 1's own
|
|
1403
|
+
template untouched. AND ONLY ON .ig-slot: a footer row is not that grid, so
|
|
1404
|
+
naming it here would set a column template on a box that has none. */
|
|
1405
|
+
.ig-workspace .ig-slot[data-ig-delta] {
|
|
1406
|
+
grid-template-columns: var(--ig-rank-column) 1fr auto;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/* A FOOTER ROW IS A FLEX BOX, NOT THE THREE-COLUMN GRID.
|
|
1410
|
+
|
|
1411
|
+
A ranked row reaches the trailing edge by the column template above. An
|
|
1412
|
+
excluded or tracker-held row is layer 1's .ig-footer-row — display:flex —
|
|
1413
|
+
so a chip appended to it simply follows the content it was appended after,
|
|
1414
|
+
and the frame puts it at the row's end. An auto inline margin is the flex
|
|
1415
|
+
idiom for that, and it is the right tool HERE for the same reason it was the
|
|
1416
|
+
wrong one on the grid: it moves an item within its line, and on the grid the
|
|
1417
|
+
item was in the wrong line to begin with. */
|
|
1418
|
+
.ig-workspace .ig-footer-row > .ig-delta-chip[data-placed] {
|
|
1419
|
+
margin-inline-start: auto;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
/* §17c's "write landed · order computing": the PREVIOUS order, held still and
|
|
1423
|
+
greyed one step, with the label saying why.
|
|
1424
|
+
|
|
1425
|
+
THE SAME FILTER, for the reason reevaluate/styles.ts gives where it greys
|
|
1426
|
+
.ig-reevaluate[data-order='held'] .ig-viewer: layer 1 sets color directly on
|
|
1427
|
+
its own descendants, so an inherited colour greys almost nothing, and a list
|
|
1428
|
+
of descendants to override goes stale the first time layer 1 colours
|
|
1429
|
+
something new.
|
|
1430
|
+
|
|
1431
|
+
SCOPED TO THE RAIL ZONE, WHICH THE STANDALONE SURFACE DID NOT HAVE TO BE.
|
|
1432
|
+
There, .ig-viewer is the rail and nothing else. The workspace draws a SECOND
|
|
1433
|
+
viewer in the canvas zone, and greying that one is not a smaller version of
|
|
1434
|
+
the same idea — it is the opposite of what the held state means. What is
|
|
1435
|
+
stale is the ORDER; the canvas is drawing the write states #164 put there,
|
|
1436
|
+
and pending, failed and conflict are told partly in hue. So an in-flight edit
|
|
1437
|
+
would have stripped the colour channel off the very marks that say an edit is
|
|
1438
|
+
in flight. The rail is the only surface whose ranks the store cannot vouch
|
|
1439
|
+
for, so it is the only one greyed. */
|
|
1440
|
+
.ig-workspace[data-order='held'] .ig-zone[data-zone='rail'] .ig-viewer {
|
|
1441
|
+
filter: grayscale(1);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
/* ── 17k's OTHER TWO LAYOUTS ───────────────────────────────────────────────
|
|
1445
|
+
|
|
1446
|
+
ONE RULE GENERATES ALL THREE, and it is the sentence 17k states outright:
|
|
1447
|
+
THE RAIL NEVER YIELDS. THE CANVAS YIELDS FIRST. THE INSPECTOR YIELDS IN
|
|
1448
|
+
BETWEEN. Because the canvas is already the zone designed to refuse (17f) and
|
|
1449
|
+
the inspector is the edit path that survives without it (17b).
|
|
1450
|
+
|
|
1451
|
+
at or above 1360 390 / 1fr / 330, three zones, as 17a
|
|
1452
|
+
1120 - 1359 rail unchanged; the inspector lifts to a 330 overlay
|
|
1453
|
+
over the canvas, opened by selection, Escape to dismiss
|
|
1454
|
+
below 1120 rail unchanged; the canvas collapses to a strip that
|
|
1455
|
+
opens full-width on demand; the inspector returns inline
|
|
1456
|
+
|
|
1457
|
+
Below roughly 860 is section 9 territory and out of scope for the package.
|
|
1458
|
+
|
|
1459
|
+
THE RAIL IS THE SAME 50 CHARACTERS IN ALL THREE. That is the whole rule, and
|
|
1460
|
+
it is the one thing to check when touching this block: measured on the demo
|
|
1461
|
+
at 1440, 1280 and 1000 the rail track reads 390 at every one of them. The
|
|
1462
|
+
layout before this shipped read 390 / 698 / 328 at 1440 and 312 / 632 / 312
|
|
1463
|
+
at 1280 — the rail giving up 78 of its 390 to keep a three-column template
|
|
1464
|
+
alive, which is the rule upside down.
|
|
1465
|
+
|
|
1466
|
+
WHY THESE ARE RANGE CONDITIONS AND NOT max-width/min-width PAIRS. A
|
|
1467
|
+
container's inline size is NOT AN INTEGER. Written as (min-width: 1360px)
|
|
1468
|
+
and (max-width: 1359px), a box measured at 1359.5 satisfies NEITHER — so the
|
|
1469
|
+
base fallback comes back, the rail drops to its 40-character measure, and
|
|
1470
|
+
the one rule 17k states outright is broken at exactly the widths a resize
|
|
1471
|
+
drags through. The same hole sits at 1119.5. 'width < 1360' and
|
|
1472
|
+
'width >= 1360' are complements with nothing between them, which is the
|
|
1473
|
+
property the layouts need and the only reason the syntax changed.
|
|
1474
|
+
|
|
1475
|
+
THE BASE STAYS THE THREE-ZONE TEMPLATE, because a surface rendered WITHOUT a
|
|
1476
|
+
mount has no container at all and no query fires: base-is-narrow would hand
|
|
1477
|
+
a static page a collapsed canvas with a control nothing is listening to. So
|
|
1478
|
+
the wide layout is the floor and the narrow ones are carved off it, widest
|
|
1479
|
+
first.
|
|
1480
|
+
|
|
1481
|
+
THESE SIT AT THE FOOT OF THE SHEET, WHICH IS LOAD-BEARING TWICE. The narrow
|
|
1482
|
+
block must come after the middle one to win where both match; and the zones'
|
|
1483
|
+
own rules have to come first, or a regex looking for the rule that defines
|
|
1484
|
+
.ig-zone[data-zone='inspector'] finds an override instead. That hazard is
|
|
1485
|
+
recorded further up this sheet and has already bitten once in layer 1.
|
|
1486
|
+
|
|
1487
|
+
NEITHER LAYOUT IS THE STYLESHEET'S ALONE. The lifted inspector opens on
|
|
1488
|
+
selection and dismisses on Escape, and the strip opens on a press — so
|
|
1489
|
+
host.ts holds two fields and render.ts publishes them on the surface
|
|
1490
|
+
root as data-canvas and data-inspector. What is NOT in the host is the
|
|
1491
|
+
width: nothing in the package asks how wide it is, per 17k's own note that
|
|
1492
|
+
a package which reads the window cannot be dropped into someone else's
|
|
1493
|
+
settings page. Each attribute is read only by the block that has a use for
|
|
1494
|
+
it, and means nothing at the other widths. */
|
|
1495
|
+
|
|
1496
|
+
/* 17k's STRIP CONTROL, RENDERED ALWAYS AND DRAWN ONLY WHEN NARROW.
|
|
1497
|
+
render.ts cannot know its own width, so the button is always in the
|
|
1498
|
+
markup and this is what keeps it off the other two layouts — display:none
|
|
1499
|
+
rather than visibility, so it is not a tab stop where it has nothing to do.
|
|
1500
|
+
The two narrow states size it themselves, below. */
|
|
1501
|
+
.ig-workspace .ig-canvas-strip {
|
|
1502
|
+
display: none;
|
|
1503
|
+
box-sizing: border-box;
|
|
1504
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
1505
|
+
background: var(--ig-surface);
|
|
1506
|
+
color: var(--ig-text-body);
|
|
1507
|
+
font-family: var(--ig-font-ui);
|
|
1508
|
+
font-size: var(--ig-font-size-small);
|
|
1509
|
+
padding: var(--ig-space-tight);
|
|
1510
|
+
cursor: pointer;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
.ig-workspace .ig-canvas-strip:focus-visible {
|
|
1514
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
1515
|
+
outline-offset: var(--ig-space-tight);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/* THE MIDDLE LAYOUT: the inspector lifts, and the rail does not move.
|
|
1519
|
+
|
|
1520
|
+
IT IS PLACED IN THE CANVAS'S GRID AREA, NOT POSITIONED OVER IT. An absolute
|
|
1521
|
+
overlay would need an offset chosen so it clears the rail, and an offset is
|
|
1522
|
+
a number that is right until someone changes a track. A grid area is not:
|
|
1523
|
+
the rail is a DIFFERENT area, so an item placed in the canvas's cannot reach
|
|
1524
|
+
it however wide it gets. Section 17d's audit overlay is positioned on the
|
|
1525
|
+
same argument one surface over, and this is that argument without the
|
|
1526
|
+
position.
|
|
1527
|
+
|
|
1528
|
+
42 CHARACTERS, THE SAME MEASURE THE WIDE LAYOUT GIVES THE INSPECTOR — 17k
|
|
1529
|
+
lifts the panel, it does not resize it. At the shipped --ig-char-width that
|
|
1530
|
+
is 327.6 against 17k's 330, the 2.4 the wide block already accounts for.
|
|
1531
|
+
|
|
1532
|
+
OPAQUE AND RAISED, because it now has the canvas underneath it rather than a
|
|
1533
|
+
border between them. --ig-elevation-overlay is the token for exactly this
|
|
1534
|
+
and --ig-surface is the raised ground; the zone keeps its own border-left
|
|
1535
|
+
from the base rule, which reads as the panel's leading edge. */
|
|
1536
|
+
@container ig-workspace (width < 1360px) {
|
|
1537
|
+
.ig-workspace {
|
|
1538
|
+
grid-template-areas:
|
|
1539
|
+
'header header'
|
|
1540
|
+
'rail canvas';
|
|
1541
|
+
grid-template-columns:
|
|
1542
|
+
calc(var(--ig-char-width) * 50)
|
|
1543
|
+
1fr;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
.ig-workspace .ig-zone[data-zone='inspector'] {
|
|
1547
|
+
grid-area: canvas;
|
|
1548
|
+
justify-self: end;
|
|
1549
|
+
inline-size: calc(var(--ig-char-width) * 42);
|
|
1550
|
+
z-index: 1;
|
|
1551
|
+
background: var(--ig-surface);
|
|
1552
|
+
box-shadow: var(--ig-elevation-overlay);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
/* OPENED BY SELECTION, DISMISSED ON ESCAPE — 17k's own words, and both
|
|
1556
|
+
halves arrive as this one attribute. render.ts writes 'lifted' only when
|
|
1557
|
+
something is SELECTED and the reader has not dismissed it since, so an
|
|
1558
|
+
empty "nothing selected" card never floats over the canvas. */
|
|
1559
|
+
.ig-workspace[data-inspector='dismissed'] .ig-zone[data-zone='inspector'] {
|
|
1560
|
+
display: none;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
/* THE NARROW LAYOUT: the canvas collapses, the inspector comes back inline,
|
|
1565
|
+
and the rail still does not move.
|
|
1566
|
+
|
|
1567
|
+
THE INSPECTOR IS RESTORED DECLARATION BY DECLARATION rather than by scoping
|
|
1568
|
+
the block above to a band, because the sheet's guard has no band to scope to.
|
|
1569
|
+
Each line here answers one line there, on the same selector so source order
|
|
1570
|
+
settles it — that is the price of single-sided conditions, paid in full and
|
|
1571
|
+
in one place.
|
|
1572
|
+
|
|
1573
|
+
THE STRIP IS 4 CHARACTERS. The canvas is the zone designed to refuse (17f),
|
|
1574
|
+
so what it yields is everything except the handle that brings it back; the
|
|
1575
|
+
inspector takes 1fr, which at 1000 is 550 and at 860 is 418 — both above the
|
|
1576
|
+
330 the wide layout gives it, so the zone that yields in between is not
|
|
1577
|
+
yielding here at all. That is the order the rule names. */
|
|
1578
|
+
@container ig-workspace (width < 1120px) {
|
|
1579
|
+
.ig-workspace {
|
|
1580
|
+
grid-template-areas:
|
|
1581
|
+
'header header header'
|
|
1582
|
+
'rail canvas inspector';
|
|
1583
|
+
grid-template-columns:
|
|
1584
|
+
calc(var(--ig-char-width) * 50)
|
|
1585
|
+
calc(var(--ig-char-width) * 4)
|
|
1586
|
+
1fr;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.ig-workspace .ig-zone[data-zone='inspector'] {
|
|
1590
|
+
grid-area: inspector;
|
|
1591
|
+
justify-self: stretch;
|
|
1592
|
+
inline-size: auto;
|
|
1593
|
+
z-index: auto;
|
|
1594
|
+
background: none;
|
|
1595
|
+
box-shadow: none;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
/* THE DISMISSAL MEANS NOTHING HERE, and saying so is the undo of the middle
|
|
1599
|
+
block's only conditional rule. The inspector is a zone again, so there is
|
|
1600
|
+
no overlay to have dismissed. */
|
|
1601
|
+
.ig-workspace[data-inspector='dismissed'] .ig-zone[data-zone='inspector'] {
|
|
1602
|
+
display: block;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
.ig-workspace[data-canvas='strip'] .ig-canvas-strip {
|
|
1606
|
+
display: block;
|
|
1607
|
+
writing-mode: vertical-rl;
|
|
1608
|
+
inline-size: 100%;
|
|
1609
|
+
block-size: 100%;
|
|
1610
|
+
overflow: hidden;
|
|
1611
|
+
white-space: nowrap;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
/* COLLAPSED MEANS GONE, NOT CLIPPED. The zone is overflow:auto, so leaving
|
|
1615
|
+
the graph in a 31-wide track would keep every node in the tab order behind
|
|
1616
|
+
a scrollbar the reader cannot use — and a keyboard reader would walk a
|
|
1617
|
+
canvas nobody can see. display:none is what takes them out of the tree,
|
|
1618
|
+
and it is reversible in one attribute.
|
|
1619
|
+
|
|
1620
|
+
TWO EXCEPTIONS, AND NEITHER IS THE CANVAS. The strip is the handle that
|
|
1621
|
+
brings the zone back. 17d's audit overlay is a sibling of the graph rather
|
|
1622
|
+
than part of it — it is anchored to the HEADER COUNT, which is drawn at
|
|
1623
|
+
every width, so a collapsed canvas taking it down would remove a surface
|
|
1624
|
+
the reader opened from a control that is still there. */
|
|
1625
|
+
.ig-workspace[data-canvas='strip']
|
|
1626
|
+
.ig-zone[data-zone='canvas']
|
|
1627
|
+
> :not(.ig-canvas-strip):not(.ig-audit-overlay) {
|
|
1628
|
+
display: none;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
/* AND THE OVERLAY HAS TO ESCAPE THE STRIP IT HANGS OFF.
|
|
1632
|
+
|
|
1633
|
+
17d positions it against the canvas ZONE, which is what keeps it off the
|
|
1634
|
+
rail without a magic offset. That argument still holds here and the
|
|
1635
|
+
ARITHMETIC does not: the zone is four characters wide, so the panel's own
|
|
1636
|
+
'width: min(66.67ch, 100% - gap)' resolves to the strip, and 'right' would
|
|
1637
|
+
anchor a wider one leftwards — across the rail, which is the one thing 17k
|
|
1638
|
+
says an overlay must never do.
|
|
1639
|
+
|
|
1640
|
+
SO THE ANCHOR FLIPS AND THE CLAMP GOES. Anchored at the zone's leading
|
|
1641
|
+
edge it opens away from the rail, into the room the inspector is using —
|
|
1642
|
+
over it, which is what an overlay is for. The zone stops clipping while it
|
|
1643
|
+
is a strip, which costs nothing: every other child is display:none above,
|
|
1644
|
+
so there is nothing else left to spill.
|
|
1645
|
+
|
|
1646
|
+
MEASURED at a 1000 mount: the zone's leading edge is 419, the rail ends at
|
|
1647
|
+
407, and 520 of panel fits in the 598 that remains. Below about 900 it
|
|
1648
|
+
runs past the trailing edge, which is the band 17k already hands to
|
|
1649
|
+
section 9. */
|
|
1650
|
+
.ig-workspace[data-canvas='strip'] .ig-zone[data-zone='canvas'] {
|
|
1651
|
+
overflow: visible;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
.ig-workspace[data-canvas='strip'] .ig-zone[data-zone='canvas'] .ig-audit-overlay {
|
|
1655
|
+
left: 0;
|
|
1656
|
+
right: auto;
|
|
1657
|
+
width: calc(var(--ig-char-width) * 66.67);
|
|
1658
|
+
max-height: 100%;
|
|
1659
|
+
/* THE SHADOW GOES WITH THE CLIPPING, and that pairing is the whole point.
|
|
1660
|
+
Section 3 forbids this panel reaching the rail ABSOLUTELY, and it is a
|
|
1661
|
+
rule about what a reader SEES — a soft edge falling across the order
|
|
1662
|
+
breaks it exactly as a border would. Everywhere else the zone's own
|
|
1663
|
+
overflow is what guarantees that; here the zone is deliberately not
|
|
1664
|
+
clipping, so the one thing that could paint outside the border box is
|
|
1665
|
+
removed instead. The panel still reads as raised: it keeps its ground
|
|
1666
|
+
and its border, over a canvas that is four characters wide and drawing
|
|
1667
|
+
nothing. */
|
|
1668
|
+
box-shadow: none;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
/* OPENED FULL-WIDTH ON DEMAND — 17k's words — and full-width is measured
|
|
1672
|
+
from the rail, which still does not yield. The inspector stands down while
|
|
1673
|
+
it is open, which is the one place this layout borrows from the middle
|
|
1674
|
+
one: the canvas is transient here in the way the panel is there. */
|
|
1675
|
+
.ig-workspace[data-canvas='open'] {
|
|
1676
|
+
grid-template-areas:
|
|
1677
|
+
'header header'
|
|
1678
|
+
'rail canvas';
|
|
1679
|
+
grid-template-columns:
|
|
1680
|
+
calc(var(--ig-char-width) * 50)
|
|
1681
|
+
1fr;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
.ig-workspace[data-canvas='open'] .ig-zone[data-zone='inspector'] {
|
|
1685
|
+
display: none;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
/* The same control closes it, so it stops being a strip and reads as a
|
|
1689
|
+
button above the canvas it opened. */
|
|
1690
|
+
.ig-workspace[data-canvas='open'] .ig-canvas-strip {
|
|
1691
|
+
display: block;
|
|
1692
|
+
justify-self: start;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
845
1695
|
`;
|
|
846
1696
|
//# sourceMappingURL=styles.js.map
|