@issuegraph/editor 0.10.0 → 0.23.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.
Files changed (113) hide show
  1. package/README.md +38 -7
  2. package/dist/a11y/baseline.d.ts.map +1 -1
  3. package/dist/a11y/baseline.js +4 -0
  4. package/dist/a11y/baseline.js.map +1 -1
  5. package/dist/audit/findings.d.ts +107 -1
  6. package/dist/audit/findings.d.ts.map +1 -1
  7. package/dist/audit/findings.js +114 -7
  8. package/dist/audit/findings.js.map +1 -1
  9. package/dist/audit/panel.d.ts +277 -0
  10. package/dist/audit/panel.d.ts.map +1 -0
  11. package/dist/audit/panel.js +462 -0
  12. package/dist/audit/panel.js.map +1 -0
  13. package/dist/audit/refused.d.ts +99 -0
  14. package/dist/audit/refused.d.ts.map +1 -0
  15. package/dist/audit/refused.js +276 -0
  16. package/dist/audit/refused.js.map +1 -0
  17. package/dist/audit/styles.d.ts +1 -1
  18. package/dist/audit/styles.d.ts.map +1 -1
  19. package/dist/audit/styles.js +428 -0
  20. package/dist/audit/styles.js.map +1 -1
  21. package/dist/audit/surface.d.ts +54 -12
  22. package/dist/audit/surface.d.ts.map +1 -1
  23. package/dist/audit/surface.js +54 -14
  24. package/dist/audit/surface.js.map +1 -1
  25. package/dist/create/draft.d.ts +19 -0
  26. package/dist/create/draft.d.ts.map +1 -1
  27. package/dist/create/draft.js +21 -0
  28. package/dist/create/draft.js.map +1 -1
  29. package/dist/create/keys.d.ts +68 -8
  30. package/dist/create/keys.d.ts.map +1 -1
  31. package/dist/create/keys.js +43 -5
  32. package/dist/create/keys.js.map +1 -1
  33. package/dist/firstpass/render.d.ts.map +1 -1
  34. package/dist/firstpass/render.js +10 -9
  35. package/dist/firstpass/render.js.map +1 -1
  36. package/dist/index.d.ts +40 -15
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +35 -13
  39. package/dist/index.js.map +1 -1
  40. package/dist/overlay/render.d.ts +11 -3
  41. package/dist/overlay/render.d.ts.map +1 -1
  42. package/dist/overlay/render.js +24 -7
  43. package/dist/overlay/render.js.map +1 -1
  44. package/dist/overlay/request.d.ts +71 -0
  45. package/dist/overlay/request.d.ts.map +1 -0
  46. package/dist/overlay/request.js +129 -0
  47. package/dist/overlay/request.js.map +1 -0
  48. package/dist/overlay/styles.d.ts +1 -1
  49. package/dist/overlay/styles.d.ts.map +1 -1
  50. package/dist/overlay/styles.js +38 -7
  51. package/dist/overlay/styles.js.map +1 -1
  52. package/dist/reevaluate/parts.d.ts +130 -0
  53. package/dist/reevaluate/parts.d.ts.map +1 -0
  54. package/dist/reevaluate/parts.js +260 -0
  55. package/dist/reevaluate/parts.js.map +1 -0
  56. package/dist/reevaluate/render.d.ts +18 -11
  57. package/dist/reevaluate/render.d.ts.map +1 -1
  58. package/dist/reevaluate/render.js +21 -135
  59. package/dist/reevaluate/render.js.map +1 -1
  60. package/dist/reevaluate/styles.d.ts +1 -1
  61. package/dist/reevaluate/styles.d.ts.map +1 -1
  62. package/dist/reevaluate/styles.js +26 -0
  63. package/dist/reevaluate/styles.js.map +1 -1
  64. package/dist/reevaluate/view.d.ts +16 -1
  65. package/dist/reevaluate/view.d.ts.map +1 -1
  66. package/dist/reevaluate/view.js +21 -1
  67. package/dist/reevaluate/view.js.map +1 -1
  68. package/dist/reevaluate/words.d.ts +7 -0
  69. package/dist/reevaluate/words.d.ts.map +1 -1
  70. package/dist/scale/ladder.d.ts +62 -6
  71. package/dist/scale/ladder.d.ts.map +1 -1
  72. package/dist/scale/ladder.js +127 -16
  73. package/dist/scale/ladder.js.map +1 -1
  74. package/dist/scale/render.d.ts +44 -0
  75. package/dist/scale/render.d.ts.map +1 -1
  76. package/dist/scale/render.js +223 -30
  77. package/dist/scale/render.js.map +1 -1
  78. package/dist/scale/styles.d.ts +11 -5
  79. package/dist/scale/styles.d.ts.map +1 -1
  80. package/dist/scale/styles.js +185 -4
  81. package/dist/scale/styles.js.map +1 -1
  82. package/dist/workspace/host.d.ts +83 -1
  83. package/dist/workspace/host.d.ts.map +1 -1
  84. package/dist/workspace/host.js +197 -4
  85. package/dist/workspace/host.js.map +1 -1
  86. package/dist/workspace/inspector.d.ts +33 -7
  87. package/dist/workspace/inspector.d.ts.map +1 -1
  88. package/dist/workspace/inspector.js +15 -0
  89. package/dist/workspace/inspector.js.map +1 -1
  90. package/dist/workspace/mount.d.ts +23 -1
  91. package/dist/workspace/mount.d.ts.map +1 -1
  92. package/dist/workspace/mount.js +605 -20
  93. package/dist/workspace/mount.js.map +1 -1
  94. package/dist/workspace/rail.d.ts +5 -2
  95. package/dist/workspace/rail.d.ts.map +1 -1
  96. package/dist/workspace/rail.js.map +1 -1
  97. package/dist/workspace/render.d.ts +390 -3
  98. package/dist/workspace/render.d.ts.map +1 -1
  99. package/dist/workspace/render.js +924 -133
  100. package/dist/workspace/render.js.map +1 -1
  101. package/dist/workspace/selection.d.ts +11 -0
  102. package/dist/workspace/selection.d.ts.map +1 -1
  103. package/dist/workspace/selection.js +10 -0
  104. package/dist/workspace/selection.js.map +1 -1
  105. package/dist/workspace/skeleton.d.ts +33 -0
  106. package/dist/workspace/skeleton.d.ts.map +1 -0
  107. package/dist/workspace/skeleton.js +56 -0
  108. package/dist/workspace/skeleton.js.map +1 -0
  109. package/dist/workspace/styles.d.ts +1 -1
  110. package/dist/workspace/styles.d.ts.map +1 -1
  111. package/dist/workspace/styles.js +931 -19
  112. package/dist/workspace/styles.js.map +1 -1
  113. package/package.json +4 -4
@@ -29,39 +29,154 @@
29
29
  * its own refusal beside this one — two refusals about one document, one of
30
30
  * which has no routes.
31
31
  */
32
- import { element, renderMarkup, renderViewer, resolveTheme, themeCss, viewerStylesheet, } from '@issuegraph/viewer';
32
+ import { EDGE_TREATMENTS, clusterReachLabel, element, renderMarkup, renderViewer, resolveTheme, themeCss, viewerStylesheet, } from '@issuegraph/viewer';
33
33
  import { overlaysFor } from "../overlay/projected.js";
34
34
  import { attachEdgeOverlays } from "../overlay/render.js";
35
+ import { edgeMarkRequests } from "../overlay/request.js";
35
36
  import { edgeOverlayStylesheet } from "../overlay/styles.js";
36
37
  import { INITIAL_SCALE_STATE } from "./commands.js";
37
38
  import { scaleLadder, } from "./ladder.js";
38
39
  import { scaleLadderStylesheet } from "./styles.js";
40
+ /**
41
+ * What the capsule list left out, with the size range frame `17f` draws under
42
+ * it — "+ 5 more" over "2-7 issues each".
43
+ *
44
+ * THE RANGE IS THE HALF THAT SAYS WHETHER THE TAIL MATTERS. A bare count leaves
45
+ * the reader unable to tell five components of two from five of ninety, and
46
+ * only one of those is safe to leave alone. A single omitted size, or several
47
+ * of one size, states that size once rather than as a range against itself.
48
+ */
49
+ function omittedSpec(omitted) {
50
+ if (omitted === null)
51
+ return null;
52
+ const { range } = omitted;
53
+ const span = range === null
54
+ ? ''
55
+ : range.smallest === range.largest
56
+ ? ` \u00b7 ${String(range.smallest)} ${range.smallest === 1 ? 'issue' : 'issues'} each`
57
+ : ` \u00b7 ${String(range.smallest)}\u2013${String(range.largest)} issues each`;
58
+ return element('p', { class: 'ig-refusal-omitted' }, [
59
+ `${String(omitted.count)} more ${omitted.count === 1 ? 'group is' : 'groups are'} not listed${span}.`,
60
+ ]);
61
+ }
62
+ /**
63
+ * The capsule's accessible name — the same facts as a sentence.
64
+ *
65
+ * ONE FACT, ONE WORDING still holds: the reach comes from `clusterReachLabel`
66
+ * exactly as the visible text does, so the two can never describe a component
67
+ * differently. What differs is only what a glyph cannot carry.
68
+ *
69
+ * THE LEAD IS IN IT BECAUSE THE TITLE IS NOT UNIQUE. A component has no name of
70
+ * its own, so `name` is the LEAD ISSUE'S TITLE — and two components whose leads
71
+ * share a title and agree on size, blocking count and reach would otherwise
72
+ * carry the same accessible name, with no key drawn on the card to tell them
73
+ * apart either. The lead key is unique by construction, because components
74
+ * partition the document's keys; naming it keeps the guarantee the old
75
+ * `Focus <lead>` label had by accident.
76
+ */
77
+ function capsuleLabel(capsule) {
78
+ const blocking = capsule.reach.kind === 'cyclic'
79
+ ? 'has a loop'
80
+ : `${String(capsule.blockedByEdges)} blocking`;
81
+ // THE ACCESSIBLE NAME SAYS "around" TOO, so what is heard and what is drawn
82
+ // make the same claim. It used to read "Focus <title> (<key>)", which names
83
+ // the component after one issue in the one channel that cannot show the
84
+ // layout making it an anchor.
85
+ return `Draw the group around ${capsule.lead}, ${capsule.name}: ${String(capsule.size)} issues, ${blocking}, ${clusterReachLabel(capsule.reach)}`;
86
+ }
87
+ /**
88
+ * One component, as frame `17f` draws it: a card whose whole surface enters it.
89
+ *
90
+ * THE CAPSULE IS THE CONTROL, not a row with a button in it. The frame says
91
+ * "click to enter one; the spine renders inside it", and a `Focus #101` button
92
+ * beside four static spans makes the pointer target a fraction of what is drawn
93
+ * as one surface — while putting the LEAST informative thing, a raw key, first
94
+ * in the reading order.
95
+ *
96
+ * THIS IS LAYER 2 AND ONLY LAYER 2. `graph.ts` deliberately draws its §16
97
+ * capsule as an inert `li`, because that package does not narrow and a control
98
+ * there could never complete the action it advertises. Layer 2 narrows, so here
99
+ * the control is real — the same reasoning, landing on the opposite answer.
100
+ *
101
+ * ORDERED BY WHAT CHANGES BEHAVIOUR, which is the frame's own annotation:
102
+ * count, then the blocking count or the cycle that voids it, then the name,
103
+ * then the reach. The accessible name is written rather than left to the
104
+ * contents, and carries the lead key so two capsules are told apart by their
105
+ * own identity rather than by position.
106
+ */
107
+ function capsuleSpec(capsule) {
108
+ // A CELL, NOT A CAPSULE. `.ig-capsule` is layer 1's own CARD — background,
109
+ // border, radius, padding and a top margin (`viewer/src/styles.ts`) — so
110
+ // keeping it here drew a bordered box inside a bordered box, put the stuck
111
+ // tint and the hover on the INNER border only, and made the row gutter wider
112
+ // than the column gutter by that margin. Resetting it from layer 2 would be
113
+ // redefining a layer 1 class, which this package's stylesheet opens by
114
+ // refusing to do; the list item simply stops claiming to be one.
115
+ return element('li', { class: 'ig-capsule-cell' }, [
116
+ element('button', {
117
+ type: 'button',
118
+ class: 'ig-capsule-enter',
119
+ 'data-ig-command': 'focus',
120
+ 'data-ig-target': capsule.lead,
121
+ // THE REACH AS AN ATTRIBUTE, so the frame's tint on a stuck card is a
122
+ // rule rather than a second branch in the markup, and a host styling
123
+ // the board can reach the same distinction.
124
+ 'data-reach': capsule.reach.kind,
125
+ // WRITTEN, NOT LEFT TO THE CONTENTS. `element` concatenates children
126
+ // with no whitespace — the trap `.ig-isolated-list` already records —
127
+ // so the four parts below would reach a screen reader as one run:
128
+ // "20\u2298 19Issue c0-1deepest chain 19". The gap that separates them
129
+ // is CSS, which the accessibility tree does not read. This also spells
130
+ // out the glyph, which is a shape with no name of its own.
131
+ 'aria-label': capsuleLabel(capsule),
132
+ }, [
133
+ element('span', { class: 'ig-capsule-size' }, [String(capsule.size)]),
134
+ // THE CYCLE STANDS WHERE THE BLOCKING COUNT STANDS. On a stuck
135
+ // component the number of blocking edges is not the fact that changes
136
+ // what the reader does: none of the members is reachable however few
137
+ // there are.
138
+ //
139
+ // NEITHER SLOT TAKES `.ig-count`, and that is not a style preference:
140
+ // layer 1 gives that class a cell's padding (`styles.ts`), which inside
141
+ // a card indents the text off the grid line the count above it sits on.
142
+ // The `ig-capsule-*` classes are this card's own, so it can place its
143
+ // four parts without editing a class §16's capsule also draws.
144
+ capsule.reach.kind === 'cyclic'
145
+ ? element('span', { class: 'ig-capsule-load ig-badge', 'data-edge': 'blocked-by' }, [
146
+ 'cycle',
147
+ ])
148
+ : element('span', { class: 'ig-capsule-load' }, [
149
+ `${EDGE_TREATMENTS['blocked-by'].glyph} ${String(capsule.blockedByEdges)}`,
150
+ ]),
151
+ // THE ANCHOR, WORDED AS ONE. `RULINGS.md` §4: a capsule is identified
152
+ // by "around #488 · Extract session store adapter", never by a name —
153
+ // because a connected component HAS no name and one must not be
154
+ // invented. The title alone read as the component's name, which is a
155
+ // claim about a seventy-two issue group made from one member's title.
156
+ //
157
+ // ONE HARDCODED WORD, AND IT IS FLAGGED RATHER THAN HIDDEN. This
158
+ // surface takes no words port — `capsuleLabel` above already spells
159
+ // "Focus" in English — so "around" joins it. That is a gap in this
160
+ // module, not a decision: the rest of this package hands every sentence
161
+ // to the host, and a scale surface that cannot be translated is worth
162
+ // fixing when the port is added.
163
+ element('span', { class: 'ig-capsule-name' }, [
164
+ element('span', { class: 'ig-capsule-anchor' }, ['around ']),
165
+ element('span', { class: 'ig-id' }, [capsule.lead]),
166
+ ' \u00b7 ',
167
+ capsule.name,
168
+ ]),
169
+ element('span', { class: 'ig-capsule-reach' }, [clusterReachLabel(capsule.reach)]),
170
+ ]),
171
+ ]);
172
+ }
39
173
  function refusalSpec(refusal, ladder) {
40
174
  return element('section', { class: 'ig-refusal', role: 'note' }, [
41
175
  element('p', {}, [refusal.reason]),
42
176
  ladder.capsules.length === 0
43
177
  ? null
44
- : element('ol', { class: 'ig-list', 'aria-label': 'connected components' }, ladder.capsules.map((capsule) => element('li', { class: 'ig-capsule' }, [
45
- element('button', {
46
- type: 'button',
47
- 'data-ig-command': 'focus',
48
- 'data-ig-target': capsule.lead,
49
- }, [`Focus ${capsule.lead}`]),
50
- element('span', { class: 'ig-count' }, [`${String(capsule.size)} issues`]),
51
- element('span', { class: 'ig-count' }, [
52
- `${String(capsule.blockedByEdges)} blocking`,
53
- ]),
54
- element('span', { class: 'ig-count' }, [`depth ${String(capsule.chainDepth)}`]),
55
- capsule.hasCycle
56
- ? element('span', { class: 'ig-badge', 'data-edge': 'blocked-by' }, ['cycle'])
57
- : null,
58
- element('span', { class: 'ig-id' }, [capsule.members.slice(0, 3).join(', ')]),
59
- ]))),
60
- ladder.capsulesOmitted > 0
61
- ? element('p', { class: 'ig-refusal-omitted' }, [
62
- `${String(ladder.capsulesOmitted)} further ${ladder.capsulesOmitted === 1 ? 'component is' : 'components are'} not listed.`,
63
- ])
64
- : null,
178
+ : element('ol', { class: 'ig-list', 'aria-label': 'groups of related issues' }, ladder.capsules.map((capsule) => capsuleSpec(capsule))),
179
+ omittedSpec(ladder.capsulesOmitted),
65
180
  element('ul', { class: 'ig-ladder-routes', 'aria-label': 'what to do next' }, refusal.routes.map((route) => element('li', { class: 'ig-refusal-next', 'data-route': route.kind }, [route.label]))),
66
181
  ]);
67
182
  }
@@ -73,7 +188,7 @@ function searchSpec(search) {
73
188
  // resolve to whichever came first — so one of the two search boxes would
74
189
  // silently lose its label.
75
190
  element('label', {}, [
76
- 'Search to focus a component',
191
+ 'Search for an issue',
77
192
  element('input', {
78
193
  type: 'search',
79
194
  'data-ig-command': 'search',
@@ -84,7 +199,7 @@ function searchSpec(search) {
84
199
  search.matches.length === 0
85
200
  ? null
86
201
  : element('ol', { class: 'ig-list', 'aria-label': 'search matches' }, search.matches.map((match) => element('li', { class: 'ig-ladder-match' }, [
87
- element('button', { type: 'button', 'data-ig-command': 'focus', 'data-ig-target': match.lead }, [`Focus ${match.key}`]),
202
+ element('button', { type: 'button', 'data-ig-command': 'focus', 'data-ig-target': match.lead }, [`Show ${match.key}`]),
88
203
  element('span', { class: 'ig-title' }, [match.title]),
89
204
  ]))),
90
205
  search.omitted > 0
@@ -94,23 +209,80 @@ function searchSpec(search) {
94
209
  : null,
95
210
  ]);
96
211
  }
97
- function isolatedSpec(isolated) {
212
+ /**
213
+ * The isolated set: a chip that toggles it, and the list it opens.
214
+ *
215
+ * `chip` DROPS THE CONTROL AND KEEPS THE LIST, which is the whole shape
216
+ * `ScaleLadderOptions.isolatedChip` needs. A caller drawing the toggle
217
+ * elsewhere still has nowhere of its own to put 248 rows: the workspace's rail
218
+ * is VIRTUALIZED — `railRowAt` maps a scroll offset to a row index by
219
+ * `floor((scrollTop - chrome) / pitch)` — so a list of arbitrary height inside
220
+ * that track makes every offset below it name the wrong row, and the window
221
+ * re-cuts against a geometry that no longer holds. This zone has no such
222
+ * arithmetic, so the list stays here and only the control moves.
223
+ */
224
+ function isolatedSpec(isolated, chip, listId) {
98
225
  // NOTHING IS DRAWN FOR AN EMPTY SET. A chip reading "0 isolated issues" is a
99
226
  // control that opens nothing, and the count IS the information these issues
100
227
  // carry — so with no issues there is nothing to say.
101
228
  if (isolated.count === 0)
102
229
  return null;
230
+ // NO CONTROL AND NOTHING OPEN IS NOTHING AT ALL. A caller that drew the chip
231
+ // elsewhere leaves this with only the list to draw, and a shut list is no
232
+ // list — so the wrapper would be an empty bordered box, which is the chrome
233
+ // carrying no fact that the count-zero rule above already refuses.
234
+ if (!chip && !isolated.open)
235
+ return null;
103
236
  return element('div', { class: 'ig-ladder-isolated' }, [
104
- element('button', {
237
+ // A CAPTION WHEN THE CONTROL IS SOMEWHERE ELSE, AND THE HOST'S OWN WORD FOR
238
+ // IT. With the chip drawn here the button says what the list is and a
239
+ // caption above it would say it twice. §17a moves the control to the rail
240
+ // footer, and what was left in this zone was an unlabelled column of issues
241
+ // in a canvas that had been drawing a graph a moment earlier — a reader who
242
+ // scrolled to it met a list with nothing saying what it was a list OF.
243
+ //
244
+ // NO NEW WORD IS INVENTED: this is `isolated.label`, the same string the
245
+ // chip would have carried, and exactly one of the two is ever drawn. That
246
+ // keeps the surface's rule — it renders words it was given — with no
247
+ // addition to the vocabulary a host has to supply.
248
+ chip || !isolated.open
249
+ ? null
250
+ : element('p', { class: 'ig-isolated-caption' }, [isolated.label]),
251
+ !chip ? null : element('button', {
105
252
  type: 'button',
106
253
  class: 'ig-chip',
107
254
  'aria-expanded': isolated.open ? 'true' : 'false',
255
+ // NO `aria-controls` WHEN THIS CHIP IS THE CONTROL, AND THAT IS NOT AN
256
+ // OMISSION. The list is this button's immediate next sibling, so the
257
+ // relationship is already there in reading order; `aria-controls` earns
258
+ // its keep for a REMOTE disclosure, which is why the workspace's footer
259
+ // carries one and this does not.
260
+ //
261
+ // AND A FIXED ID HERE WOULD BE A DEFECT, not a shortcut. `searchSpec`
262
+ // below nests its input inside its label precisely so it needs no `id`,
263
+ // recording that "a host rendering two documents side by side would emit
264
+ // it twice" — the same host, the same page, and the second list would
265
+ // then answer to the first surface's button. An earlier revision of this
266
+ // file shipped a module constant with a comment claiming fixed ids were
267
+ // the norm on these surfaces; the control ten lines down had already
268
+ // decided otherwise.
269
+ ...(isolated.open && listId !== undefined ? { 'aria-controls': listId } : {}),
108
270
  'data-ig-command': isolated.open ? 'close-isolated' : 'open-isolated',
109
271
  }, [isolated.label]),
110
272
  // A LIST, NEVER A CANVAS. These issues have no relationship to draw, which
111
273
  // is exactly why they were collapsed in the first place.
112
274
  isolated.open
113
- ? element('ol', { class: 'ig-isolated-list', 'aria-label': 'isolated issues' }, isolated.issues.map((issue) => element('li', {}, [
275
+ ? element('ol',
276
+ // THE ID IS THE CALLER'S, OR THERE IS NONE. Only a caller drawing the
277
+ // control somewhere else needs to name this list, and only that caller
278
+ // knows what else is on its page — so it mints the value and passes it
279
+ // to both halves. This renderer inventing one would be the collision
280
+ // `searchSpec` avoids.
281
+ {
282
+ class: 'ig-isolated-list',
283
+ ...(listId === undefined ? {} : { id: listId }),
284
+ 'aria-label': 'isolated issues',
285
+ }, isolated.issues.map((issue) => element('li', {}, [
114
286
  element('span', { class: 'ig-id' }, [issue.key]),
115
287
  element('span', { class: 'ig-title' }, [issue.title]),
116
288
  ])))
@@ -122,6 +294,14 @@ export function renderScaleLadder(input, options = {}) {
122
294
  const state = options.state ?? INITIAL_SCALE_STATE;
123
295
  const ladder = scaleLadder(input, state);
124
296
  const theme = resolveTheme(options.theme);
297
+ // THE OVERLAYS ARE RESOLVED BEFORE THE CANVAS IS DRAWN, because the marks
298
+ // among them are an INPUT to the drawing rather than something added over it.
299
+ // A mark needs a position, and the only layer that has one is the layer that
300
+ // computes the layout — so the request goes in with the render and the placed
301
+ // marks come back inside the scene. The stroke-derived overlays still go the
302
+ // other way, attached to the scene afterwards, because those reuse a position
303
+ // that is already solved.
304
+ const requestedOverlays = overlaysFor(ladder.canvas.edges, options.projected, options.selectedEdge);
125
305
  const canvas = ladder.tier === 'direct'
126
306
  ? renderViewer(ladder.canvas, {
127
307
  projection: 'graph',
@@ -131,6 +311,16 @@ export function renderScaleLadder(input, options = {}) {
131
311
  // drawing it. Two would mean two projection toggles disagreeing
132
312
  // about which projection is current.
133
313
  chrome: false,
314
+ // THE WORKSPACE RULES ITS OWN ZONES OFF, so the viewer draws no
315
+ // frame of its own here: the rail track carries `border-right`, the
316
+ // canvas toolbar carries `border-bottom`, and a second edge one
317
+ // pixel away reads as a doubled hairline. See `SceneOptions.frame`.
318
+ frame: false,
319
+ // §16b's KEY, KEPT IN VIEW. It explains every line and station on this
320
+ // zone, and below a scroll it was the one thing a reader had to leave the
321
+ // reading to reach. See `SceneOptions.dockLegend`.
322
+ dockLegend: true,
323
+ edgeMarks: edgeMarkRequests(requestedOverlays),
134
324
  })
135
325
  : null;
136
326
  // THE SELECTION HALO AND THE WRITE STATES, attached to the scene the canvas
@@ -140,7 +330,7 @@ export function renderScaleLadder(input, options = {}) {
140
330
  // promise every zone makes. A selection is a NAME, and a name that no longer
141
331
  // resolves renders as nothing selected. The merge itself is `overlaysFor`,
142
332
  // shared with the workspace's tree canvas so the two cannot drift.
143
- const overlays = canvas === null ? [] : overlaysFor(ladder.canvas.edges, options.projected, options.selectedEdge);
333
+ const overlays = canvas === null ? [] : requestedOverlays;
144
334
  // `unattached` IS DELIBERATELY NOT SURFACED HERE, and the reason is a fact
145
335
  // about this call site rather than about the value.
146
336
  //
@@ -160,10 +350,13 @@ export function renderScaleLadder(input, options = {}) {
160
350
  const chrome = element('section', { class: 'ig-ladder', 'data-tier': ladder.tier }, [
161
351
  ladder.focus === null
162
352
  ? null
163
- : element('button', { type: 'button', class: 'ig-chip', 'data-ig-command': 'clear-focus' }, ['Return to every component']),
353
+ : element('button', { type: 'button', class: 'ig-chip', 'data-ig-command': 'clear-focus' }, ['Go back to all groups']),
164
354
  ladder.refusal === null ? null : refusalSpec(ladder.refusal, ladder),
165
355
  ladder.search === null ? null : searchSpec(ladder.search),
166
- isolatedSpec(ladder.isolated),
356
+ // THE CONTROL, UNLESS THE CALLER DREW IT — the LIST is drawn either way.
357
+ // See `ScaleLadderOptions.isolatedChip`, and `ladder.ts`'s `searchFor` for
358
+ // why there has to be a route at all.
359
+ isolatedSpec(ladder.isolated, options.isolatedChip ?? true, options.isolatedListId),
167
360
  ]);
168
361
  return {
169
362
  ladder,
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/scale/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/scale/render.ts"],"names":[],"mappings":"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"}
@@ -8,14 +8,20 @@
8
8
  * scans these bytes for a literal colour or a fixed length and for a token the
9
9
  * theme does not define, so the rule is enforced rather than remembered.
10
10
  *
11
- * IT ADDS SELECTORS RATHER THAN REDEFINING THEM. The refusal, its capsules and
12
- * their counts already have a look — this file styles only what layer 2
13
- * introduces: the ladder container, the routes, the search box, the isolated
14
- * chip and the list it opens.
11
+ * IT ADDS SELECTORS RATHER THAN REDEFINING THEM, with ONE declared exception.
12
+ * The refusal and its counts already have a look, so this file styles what
13
+ * layer 2 introduces: the ladder container, the routes, the search box, the
14
+ * isolated chip, the list it opens, and §17f's capsule card. The exception is
15
+ * `.ig-ladder .ig-refusal .ig-list`, which lays layer 1's list out as a board —
16
+ * declared here because the arrangement is this surface's, and scoped so §16's
17
+ * single-column list and the ladder's own search matches are untouched. The
18
+ * capsule CARD is a new class rather than a redefinition of `.ig-capsule` for
19
+ * the same reason, which is why the list item beside it carries no layer 1
20
+ * class at all.
15
21
  *
16
22
  * Shipped as a string for the same reason the viewer's is: an entry that
17
23
  * imports CSS cannot be loaded by a bare Node runtime, and a string needs no
18
24
  * bundler.
19
25
  */
20
- export declare const scaleLadderStylesheet = "\n.ig-ladder {\n display: flex;\n flex-direction: column;\n gap: var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n line-height: var(--ig-line-height);\n color: var(--ig-text-body);\n}\n\n.ig-ladder-routes {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n color: var(--ig-text-muted);\n font-size: var(--ig-font-size-small);\n}\n\n.ig-ladder-search {\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n}\n\n.ig-ladder-search input {\n background: var(--ig-surface);\n color: var(--ig-text);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n}\n\n.ig-ladder-search input:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-ladder-match {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n}\n\n.ig-chip {\n align-self: flex-start;\n background: var(--ig-surface-2);\n color: var(--ig-text-body);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight) var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size-small);\n cursor: pointer;\n}\n\n.ig-chip:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-chip[aria-expanded='true'] {\n border-color: var(--ig-accent);\n color: var(--ig-text);\n}\n\n.ig-isolated-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n}\n\n.ig-isolated-list .ig-id {\n font-family: var(--ig-font-mono);\n color: var(--ig-text-muted);\n}\n";
26
+ export declare const scaleLadderStylesheet = "\n.ig-ladder {\n display: flex;\n flex-direction: column;\n gap: var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n line-height: var(--ig-line-height);\n color: var(--ig-text-body);\n}\n\n.ig-ladder-routes {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n color: var(--ig-text-muted);\n font-size: var(--ig-font-size-small);\n}\n\n.ig-ladder-search {\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n}\n\n.ig-ladder-search input {\n background: var(--ig-surface);\n color: var(--ig-text);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n}\n\n.ig-ladder-search input:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-ladder-match {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n}\n\n.ig-chip {\n align-self: flex-start;\n background: var(--ig-surface-2);\n color: var(--ig-text-body);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight) var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size-small);\n cursor: pointer;\n}\n\n.ig-chip:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-chip[aria-expanded='true'] {\n border-color: var(--ig-accent);\n color: var(--ig-text);\n}\n\n/* THE LIST ITEM IS A GRID CELL AND NOTHING ELSE. It deliberately does not\n carry .ig-capsule: that is layer 1's own card, and a card inside a card put\n the stuck tint and the hover on the inner border only. */\n.ig-capsule-cell {\n display: flex;\n min-width: 0;\n}\n\n/* FOUR CARDS ACROSS A COLUMN, NOT FOUR ROWS DOWN IT. Frame 17f lays the\n capsules out as a board, which is what makes the counts comparable at a\n glance \u2014 the whole reason the count leads. minmax(0, 1fr) rather than a\n width, because this stylesheet declares no fixed length: a title is arbitrary\n and auto would let the longest one set every column. Scoped to the ladder's\n own refusal so \u00A716's single-column list, drawn from the same class in layer\n 1, is untouched. */\n.ig-ladder .ig-refusal .ig-list {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--ig-space);\n}\n\n/* THE WHOLE CAPSULE IS THE CONTROL, so the button carries the card and the\n list item carries nothing. A button wrapping a card needs its own alignment\n and wrapping reset: a user agent centres and nowraps button content, and both\n are wrong for a four-part card with a title in it. */\n.ig-capsule-enter {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: start;\n gap: var(--ig-space-tight) var(--ig-space);\n width: 100%;\n height: 100%;\n text-align: left;\n background: var(--ig-surface-2);\n color: var(--ig-text-body);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n cursor: pointer;\n}\n\n.ig-capsule-enter:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-capsule-enter:hover {\n border-color: var(--ig-accent);\n}\n\n/* THE WHOLE STUCK CARD IS TINTED, as frame 17f draws it \u2014 the badge alone puts\n the one finding that stops work outright at the size of every other chip on\n the board. Same hue as the badge inside it, which is blocked-by's, because\n that is the edge the cycle is made of. */\n.ig-capsule-enter[data-reach='cyclic'] {\n border-color: var(--ig-edge-blocked-by);\n}\n\n.ig-capsule-enter[data-reach='cyclic'] .ig-capsule-reach {\n color: var(--ig-edge-blocked-by);\n}\n\n/* THE COUNT LEADS, so it is the one part sized to be read down the board rather\n than within a card. The --ig-font-size-rank token is the one the theme defines\n for exactly this \u2014 \"the rank number itself\" \u2014 so a capsule's count and a rail\n rank are one size by declaration rather than by coincidence. */\n.ig-capsule-size {\n grid-column: 1;\n font-family: var(--ig-font-mono);\n font-size: var(--ig-font-size-rank);\n font-variant-numeric: tabular-nums;\n color: var(--ig-text);\n}\n\n/* END-ALIGNED AND CONTENT-WIDTH. A grid item stretches by default, which drew\n the cycle badge as a full-width bar across the top of the card. The pill is\n the frame's: the blocked count and the cycle sit in one slot, so they read as\n one kind of thing rather than as a bordered badge beside bare text. */\n.ig-capsule-load {\n grid-column: 2;\n justify-self: end;\n background: var(--ig-bg);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-micro) var(--ig-space-snug);\n font-family: var(--ig-font-mono);\n font-size: var(--ig-font-size-small);\n font-variant-numeric: tabular-nums;\n color: var(--ig-text-muted);\n}\n\n/* THE NAME AND THE REACH SPAN BOTH COLUMNS, and the name is the one part\n allowed to wrap: a title is arbitrary length, and letting it size the grid\n would make every card on the board a different shape. */\n.ig-capsule-name {\n grid-column: 1 / -1;\n color: var(--ig-text);\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.ig-capsule-reach {\n grid-column: 1 / -1;\n color: var(--ig-text-muted);\n font-size: var(--ig-font-size-small);\n font-variant-numeric: tabular-nums;\n}\n\n/* A PANEL, NOT A LOOSE COLUMN OF TEXT. With the control moved to the rail\n footer (\u00A717a) this wrapper was left holding an unstyled ol at zero inset:\n it began hard against the zone's own rule, ran on from the graph above it\n with nothing between them, and read as content that had escaped a container\n rather than as the thing the reader had just asked to see.\n\n THE TOP RULE AND THE PADDING ARE THE CANVAS TOOLBAR'S, because this is the\n same kind of band one row lower \u2014 a full-bleed section of the canvas zone,\n not a card floating on it. --ig-bg for the same reason the toolbar takes\n it: the ground this zone already paints, so the two read as one surface. */\n.ig-ladder-isolated {\n border-top: var(--ig-stroke) solid var(--ig-line);\n padding: var(--ig-space) var(--ig-space-wide);\n}\n\n/* A SECTION HEAD IN THE READ-OUT VOICE the canvas caption and the rail footer\n count already use on this surface \u2014 mono, micro, muted, tracked \u2014 because it\n carries the same kind of fact and a heavier treatment would make a list of\n issues nobody has to act on the loudest thing in the zone. */\n.ig-isolated-caption {\n margin: 0 0 var(--ig-space-tight);\n color: var(--ig-text-muted);\n font-family: var(--ig-font-mono);\n font-size: var(--ig-font-size-micro);\n letter-spacing: var(--ig-tracking-group);\n text-transform: uppercase;\n}\n\n.ig-isolated-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n/* A ROW PER ENTRY, WITH A GAP THE MARKUP DOES NOT SUPPLY. The element helper\n concatenates its children with no whitespace, so the key and the title\n rendered as one run of text \u2014 #492Audit log pagination. Latent until \u00A717a\n moved the CONTROL to the rail footer and made this list the thing a reader is\n sent to, rather than a chip's afterthought. */\n/* SEPARATED THE WAY EVERY OTHER LIST OF ISSUES ON THIS SURFACE IS, with a\n hairline between rows rather than a gap between them. A gap left five lines\n of text floating in a column; the rule is what makes them read as rows, and\n it is the treatment the viewer's own order rows already carry. Last row\n included would double the zone's next edge, so it stops one short. */\n.ig-isolated-list li {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n min-width: 0;\n padding: var(--ig-space-tight) 0;\n}\n\n.ig-isolated-list li + li {\n border-top: var(--ig-stroke) solid var(--ig-line);\n}\n\n/* THE KEY IN ITS OWN COLUMN, so five titles start on one edge rather than\n wherever their number happened to end. tabular-nums and a measure in\n characters are what the capsule's own count line already uses for the same\n reason: a ragged left edge on a column of ids reads as a mistake. */\n.ig-isolated-list .ig-id {\n font-family: var(--ig-font-mono);\n font-size: var(--ig-font-size-small);\n font-variant-numeric: tabular-nums;\n color: var(--ig-text-muted);\n flex: none;\n min-inline-size: calc(var(--ig-char-width) * 5);\n}\n\n/* The title carries the row, so it takes the body colour and wraps rather than\n setting the row's width \u2014 the rule .ig-capsule-name states one file up. */\n.ig-isolated-list .ig-title {\n color: var(--ig-text);\n min-width: 0;\n overflow-wrap: anywhere;\n}\n";
21
27
  //# sourceMappingURL=styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/scale/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,qBAAqB,23DAoFjC,CAAC"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/scale/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,eAAO,MAAM,qBAAqB,g5RAmQjC,CAAC"}
@@ -8,10 +8,16 @@
8
8
  * scans these bytes for a literal colour or a fixed length and for a token the
9
9
  * theme does not define, so the rule is enforced rather than remembered.
10
10
  *
11
- * IT ADDS SELECTORS RATHER THAN REDEFINING THEM. The refusal, its capsules and
12
- * their counts already have a look — this file styles only what layer 2
13
- * introduces: the ladder container, the routes, the search box, the isolated
14
- * chip and the list it opens.
11
+ * IT ADDS SELECTORS RATHER THAN REDEFINING THEM, with ONE declared exception.
12
+ * The refusal and its counts already have a look, so this file styles what
13
+ * layer 2 introduces: the ladder container, the routes, the search box, the
14
+ * isolated chip, the list it opens, and §17f's capsule card. The exception is
15
+ * `.ig-ladder .ig-refusal .ig-list`, which lays layer 1's list out as a board —
16
+ * declared here because the arrangement is this surface's, and scoped so §16's
17
+ * single-column list and the ladder's own search matches are untouched. The
18
+ * capsule CARD is a new class rather than a redefinition of `.ig-capsule` for
19
+ * the same reason, which is why the list item beside it carries no layer 1
20
+ * class at all.
15
21
  *
16
22
  * Shipped as a string for the same reason the viewer's is: an entry that
17
23
  * imports CSS cannot be loaded by a bare Node runtime, and a string needs no
@@ -88,18 +94,193 @@ export const scaleLadderStylesheet = `
88
94
  color: var(--ig-text);
89
95
  }
90
96
 
97
+ /* THE LIST ITEM IS A GRID CELL AND NOTHING ELSE. It deliberately does not
98
+ carry .ig-capsule: that is layer 1's own card, and a card inside a card put
99
+ the stuck tint and the hover on the inner border only. */
100
+ .ig-capsule-cell {
101
+ display: flex;
102
+ min-width: 0;
103
+ }
104
+
105
+ /* FOUR CARDS ACROSS A COLUMN, NOT FOUR ROWS DOWN IT. Frame 17f lays the
106
+ capsules out as a board, which is what makes the counts comparable at a
107
+ glance — the whole reason the count leads. minmax(0, 1fr) rather than a
108
+ width, because this stylesheet declares no fixed length: a title is arbitrary
109
+ and auto would let the longest one set every column. Scoped to the ladder's
110
+ own refusal so §16's single-column list, drawn from the same class in layer
111
+ 1, is untouched. */
112
+ .ig-ladder .ig-refusal .ig-list {
113
+ display: grid;
114
+ grid-template-columns: repeat(2, minmax(0, 1fr));
115
+ gap: var(--ig-space);
116
+ }
117
+
118
+ /* THE WHOLE CAPSULE IS THE CONTROL, so the button carries the card and the
119
+ list item carries nothing. A button wrapping a card needs its own alignment
120
+ and wrapping reset: a user agent centres and nowraps button content, and both
121
+ are wrong for a four-part card with a title in it. */
122
+ .ig-capsule-enter {
123
+ display: grid;
124
+ grid-template-columns: 1fr auto;
125
+ align-items: start;
126
+ gap: var(--ig-space-tight) var(--ig-space);
127
+ width: 100%;
128
+ height: 100%;
129
+ text-align: left;
130
+ background: var(--ig-surface-2);
131
+ color: var(--ig-text-body);
132
+ border: var(--ig-stroke) solid var(--ig-line);
133
+ border-radius: var(--ig-radius);
134
+ padding: var(--ig-space);
135
+ font-family: var(--ig-font-ui);
136
+ font-size: var(--ig-font-size);
137
+ cursor: pointer;
138
+ }
139
+
140
+ .ig-capsule-enter:focus-visible {
141
+ outline: var(--ig-focus-ring) solid var(--ig-focus);
142
+ outline-offset: var(--ig-space-tight);
143
+ }
144
+
145
+ .ig-capsule-enter:hover {
146
+ border-color: var(--ig-accent);
147
+ }
148
+
149
+ /* THE WHOLE STUCK CARD IS TINTED, as frame 17f draws it — the badge alone puts
150
+ the one finding that stops work outright at the size of every other chip on
151
+ the board. Same hue as the badge inside it, which is blocked-by's, because
152
+ that is the edge the cycle is made of. */
153
+ .ig-capsule-enter[data-reach='cyclic'] {
154
+ border-color: var(--ig-edge-blocked-by);
155
+ }
156
+
157
+ .ig-capsule-enter[data-reach='cyclic'] .ig-capsule-reach {
158
+ color: var(--ig-edge-blocked-by);
159
+ }
160
+
161
+ /* THE COUNT LEADS, so it is the one part sized to be read down the board rather
162
+ than within a card. The --ig-font-size-rank token is the one the theme defines
163
+ for exactly this — "the rank number itself" — so a capsule's count and a rail
164
+ rank are one size by declaration rather than by coincidence. */
165
+ .ig-capsule-size {
166
+ grid-column: 1;
167
+ font-family: var(--ig-font-mono);
168
+ font-size: var(--ig-font-size-rank);
169
+ font-variant-numeric: tabular-nums;
170
+ color: var(--ig-text);
171
+ }
172
+
173
+ /* END-ALIGNED AND CONTENT-WIDTH. A grid item stretches by default, which drew
174
+ the cycle badge as a full-width bar across the top of the card. The pill is
175
+ the frame's: the blocked count and the cycle sit in one slot, so they read as
176
+ one kind of thing rather than as a bordered badge beside bare text. */
177
+ .ig-capsule-load {
178
+ grid-column: 2;
179
+ justify-self: end;
180
+ background: var(--ig-bg);
181
+ border: var(--ig-stroke) solid var(--ig-line);
182
+ border-radius: var(--ig-radius);
183
+ padding: var(--ig-space-micro) var(--ig-space-snug);
184
+ font-family: var(--ig-font-mono);
185
+ font-size: var(--ig-font-size-small);
186
+ font-variant-numeric: tabular-nums;
187
+ color: var(--ig-text-muted);
188
+ }
189
+
190
+ /* THE NAME AND THE REACH SPAN BOTH COLUMNS, and the name is the one part
191
+ allowed to wrap: a title is arbitrary length, and letting it size the grid
192
+ would make every card on the board a different shape. */
193
+ .ig-capsule-name {
194
+ grid-column: 1 / -1;
195
+ color: var(--ig-text);
196
+ min-width: 0;
197
+ overflow-wrap: anywhere;
198
+ }
199
+
200
+ .ig-capsule-reach {
201
+ grid-column: 1 / -1;
202
+ color: var(--ig-text-muted);
203
+ font-size: var(--ig-font-size-small);
204
+ font-variant-numeric: tabular-nums;
205
+ }
206
+
207
+ /* A PANEL, NOT A LOOSE COLUMN OF TEXT. With the control moved to the rail
208
+ footer (§17a) this wrapper was left holding an unstyled ol at zero inset:
209
+ it began hard against the zone's own rule, ran on from the graph above it
210
+ with nothing between them, and read as content that had escaped a container
211
+ rather than as the thing the reader had just asked to see.
212
+
213
+ THE TOP RULE AND THE PADDING ARE THE CANVAS TOOLBAR'S, because this is the
214
+ same kind of band one row lower — a full-bleed section of the canvas zone,
215
+ not a card floating on it. --ig-bg for the same reason the toolbar takes
216
+ it: the ground this zone already paints, so the two read as one surface. */
217
+ .ig-ladder-isolated {
218
+ border-top: var(--ig-stroke) solid var(--ig-line);
219
+ padding: var(--ig-space) var(--ig-space-wide);
220
+ }
221
+
222
+ /* A SECTION HEAD IN THE READ-OUT VOICE the canvas caption and the rail footer
223
+ count already use on this surface — mono, micro, muted, tracked — because it
224
+ carries the same kind of fact and a heavier treatment would make a list of
225
+ issues nobody has to act on the loudest thing in the zone. */
226
+ .ig-isolated-caption {
227
+ margin: 0 0 var(--ig-space-tight);
228
+ color: var(--ig-text-muted);
229
+ font-family: var(--ig-font-mono);
230
+ font-size: var(--ig-font-size-micro);
231
+ letter-spacing: var(--ig-tracking-group);
232
+ text-transform: uppercase;
233
+ }
234
+
91
235
  .ig-isolated-list {
92
236
  list-style: none;
93
237
  margin: 0;
94
238
  padding: 0;
95
239
  display: flex;
96
240
  flex-direction: column;
241
+ }
242
+
243
+ /* A ROW PER ENTRY, WITH A GAP THE MARKUP DOES NOT SUPPLY. The element helper
244
+ concatenates its children with no whitespace, so the key and the title
245
+ rendered as one run of text — #492Audit log pagination. Latent until §17a
246
+ moved the CONTROL to the rail footer and made this list the thing a reader is
247
+ sent to, rather than a chip's afterthought. */
248
+ /* SEPARATED THE WAY EVERY OTHER LIST OF ISSUES ON THIS SURFACE IS, with a
249
+ hairline between rows rather than a gap between them. A gap left five lines
250
+ of text floating in a column; the rule is what makes them read as rows, and
251
+ it is the treatment the viewer's own order rows already carry. Last row
252
+ included would double the zone's next edge, so it stops one short. */
253
+ .ig-isolated-list li {
254
+ display: flex;
97
255
  gap: var(--ig-space-tight);
256
+ align-items: baseline;
257
+ min-width: 0;
258
+ padding: var(--ig-space-tight) 0;
259
+ }
260
+
261
+ .ig-isolated-list li + li {
262
+ border-top: var(--ig-stroke) solid var(--ig-line);
98
263
  }
99
264
 
265
+ /* THE KEY IN ITS OWN COLUMN, so five titles start on one edge rather than
266
+ wherever their number happened to end. tabular-nums and a measure in
267
+ characters are what the capsule's own count line already uses for the same
268
+ reason: a ragged left edge on a column of ids reads as a mistake. */
100
269
  .ig-isolated-list .ig-id {
101
270
  font-family: var(--ig-font-mono);
271
+ font-size: var(--ig-font-size-small);
272
+ font-variant-numeric: tabular-nums;
102
273
  color: var(--ig-text-muted);
274
+ flex: none;
275
+ min-inline-size: calc(var(--ig-char-width) * 5);
276
+ }
277
+
278
+ /* The title carries the row, so it takes the body colour and wraps rather than
279
+ setting the row's width — the rule .ig-capsule-name states one file up. */
280
+ .ig-isolated-list .ig-title {
281
+ color: var(--ig-text);
282
+ min-width: 0;
283
+ overflow-wrap: anywhere;
103
284
  }
104
285
  `;
105
286
  //# sourceMappingURL=styles.js.map