@intentius/behold 0.29.6 → 0.29.8

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/web/kiosk.html CHANGED
@@ -16,20 +16,29 @@
16
16
  --edge: #56596d; --managed: #a6e3a1; --foreign: #f9e2af; --pending: #89b4fa;
17
17
  --degraded: #f38ba8; --neutral: #6d7187; --runtime: #94e2d5;
18
18
  --rule: #4e4f64; --focus: #a3b4d0; --active: #3d4660; --well: #11101f; --shadow: #050507;
19
+ /* behold#571: the kiosk's surfaces and ink (theme.js kioskSurfaces), the default theme's until initTheme() runs. */
20
+ --surface-box: #252536; --surface-pane-a: #2b2b3c; --surface-pane-b: #313142; --zebra: #cdd6f4; --soft: #cdd6f4; --muted-ink: #808395;
21
+ --managed-ink: #a6e3a1; --foreign-ink: #f9e2af; --pending-ink: #89b4fa; --degraded-ink: #f38ba8; --runtime-ink: #94e2d5;
19
22
  --font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
20
23
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
21
24
  }
22
25
  * { box-sizing: border-box; }
26
+ /* behold#571: the kiosk's text is the softened ink, its secondary text and state colours the ones held legible on every surface. */
27
+ body { --fg: var(--soft); --muted: var(--muted-ink); --managed: var(--managed-ink); --foreign: var(--foreign-ink); --pending: var(--pending-ink); --degraded: var(--degraded-ink); --runtime: var(--runtime-ink); --zebra-row: color-mix(in srgb, var(--zebra) 3.5%, transparent); }
23
28
  /* #569 step 3: one screen. The bar is the narration, the frame is
24
29
  behold's own view of the change, the foot is the plan's facts. Sizes
25
30
  follow the screen's width, so a TV reads it from across a room. */
26
31
  html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg); font: clamp(13px, 0.82vw, 20px)/1.4 var(--font-ui); overflow: hidden; }
27
32
  body { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
33
+ #k-head { position: relative; }
28
34
  /* #569: the pipeline's runs (left), the selected run's jobs, steps and
29
35
  log (middle), behold's view of the change (right). */
30
- #stage { display: grid; grid-template-columns: minmax(15em, 18%) minmax(26em, 34%) minmax(0, 1fr); min-height: 0; }
31
- #runs-side { overflow-y: auto; border-right: 1px solid var(--rule); background: var(--panel); }
32
- #runs-main { overflow: hidden; display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--rule); }
36
+ /* behold#571: each pane its own surface, a gap of the page between them. */
37
+ #stage { display: grid; grid-template-columns: minmax(15em, 18%) minmax(26em, 34%) minmax(0, 1fr); gap: 5px; padding: 0 5px; min-height: 0; background: var(--bg); }
38
+ #runs-side { overflow-y: auto; background: var(--surface-pane-b); border-radius: 6px 6px 0 0; }
39
+ #runs-main { overflow: hidden; display: flex; flex-direction: column; min-height: 0; background: var(--surface-pane-a); border-radius: 6px 6px 0 0; }
40
+ #k-runs-toggle { display: none; }
41
+ .r-run:nth-child(even of .r-run), .r-job:nth-child(even of .r-job), .r-log-line:nth-child(even of .r-log-line) { background: var(--zebra-row); }
33
42
  .r-side-head { padding: 0.8em 1em 0.5em; }
34
43
  .r-side-title { font-weight: 700; font-size: 1.05em; }
35
44
  .r-side-note { color: var(--muted); font-size: 0.82em; margin-top: 0.15em; }
@@ -58,6 +67,9 @@
58
67
  .r-job.r-selected { background: var(--active); }
59
68
  .r-job-name { font: 600 0.92em var(--font-mono); }
60
69
  .r-job-needs { color: var(--muted); font-size: 0.78em; }
70
+ /* behold#571: each root's colour, as a dot by its name; never a text or fill colour, which mean a state. */
71
+ .k-root::before { content: ""; display: inline-block; width: 0.6em; height: 0.6em; border-radius: 50%; background: var(--k-root); margin: 0 0.28em 0.1em 0.05em; vertical-align: middle; }
72
+ .r-job-roots { display: inline-flex; gap: 0.75em; font-size: 0.82em; color: var(--fg); }
61
73
  .r-dur { margin-left: auto; color: var(--muted); font-size: 0.8em; white-space: nowrap; }
62
74
  .r-job-skipped { color: var(--muted); font-size: 0.78em; cursor: default; }
63
75
  .r-steps { display: flex; flex-direction: column; min-height: 0; flex: 1; overflow-y: auto; padding-bottom: 0.5em; }
@@ -70,7 +82,7 @@
70
82
  .r-caret { color: var(--muted); width: 0.8em; font-size: 0.8em; }
71
83
  .r-step-name { font-size: 0.88em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
72
84
  .r-open > .r-step-line { background: color-mix(in srgb, var(--active) 60%, transparent); }
73
- .r-log { margin: 0.2em 0.6em 0.4em 1.6em; padding: 0.5em 0; background: var(--well); border-radius: 6px; font: 0.76em/1.45 var(--font-mono);
85
+ .r-log { margin: 0.2em 0.6em 0.4em 1.6em; padding: 0.5em 0; background: var(--surface-pane-b); border-radius: 6px; font: 0.76em/1.45 var(--font-mono);
74
86
  white-space: pre-wrap; overflow-wrap: anywhere; overflow-y: auto; max-height: 52vh; min-height: 6em; }
75
87
  .r-log-line { display: grid; grid-template-columns: 3.2em 1fr; gap: 0.8em; padding: 0 0.8em 0 0; }
76
88
  .r-ln { color: var(--muted); text-align: right; user-select: none; opacity: 0.7; }
@@ -83,26 +95,70 @@
83
95
  @media (prefers-reduced-motion: no-preference) { .r-log-live { animation: r-blink 1s steps(2) infinite; } }
84
96
  @keyframes r-blink { 50% { opacity: 0; } }
85
97
  .r-note { color: var(--muted); padding: 0 1em; font-size: 0.88em; }
86
- #bar { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 0.45em 1.6em; align-items: start;
87
- padding: 0.55em 1.4em 0.6em; background: var(--panel); border-bottom: 1px solid var(--rule); }
98
+ /* behold#571: a log line's feature: an outlined chip on its first line in the job, a faint dot after; its note opens under the line. */
99
+ .r-ann { font: 600 0.82em var(--font-ui); color: var(--fg); background: transparent; border: 1px solid var(--rule); border-radius: 999px; padding: 0 0.55em; margin-left: 0.3em; cursor: pointer; white-space: nowrap; vertical-align: 0.05em; }
100
+ .r-ann:hover, .r-ann:focus-visible { border-color: var(--focus); }
101
+ .r-ann-dot { display: inline-block; width: 0.55em; height: 0.55em; padding: 0; margin-left: 0.45em; border-radius: 50%; border: 0; background: var(--muted); opacity: 0.55; cursor: pointer; vertical-align: 0.1em; }
102
+ .r-ann-dot:hover { opacity: 1; }
103
+ .r-ann-terragucci { border-color: color-mix(in srgb, var(--pending) 70%, transparent); }
104
+ .r-ann-chant { border-color: color-mix(in srgb, var(--runtime) 70%, transparent); }
105
+ .r-ann-choudoufu, .r-ann-behold { border-color: color-mix(in srgb, var(--foreign) 70%, transparent); }
106
+ .r-ann-dot.r-ann-terragucci { background: var(--pending); } .r-ann-dot.r-ann-chant { background: var(--runtime); }
107
+ .r-ann-note { grid-column: 2; margin: 0.25em 0 0.45em; padding: 0.45em 0.7em; border-left: 3px solid var(--focus); background: var(--surface-box); border-radius: 0 6px 6px 0; font: 1.12em/1.4 var(--font-ui); white-space: normal; }
108
+ .r-ann-note-head { font: 600 0.8em var(--font-mono); text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); border: 0; }
109
+ .r-ann-note-text { margin: 0.15em 0 0.2em; color: var(--fg); }
110
+ .r-ann-more { color: var(--pending); }
111
+ .r-flash { background: color-mix(in srgb, var(--focus) 30%, transparent) !important; }
112
+ @media (prefers-reduced-motion: no-preference) { .r-flash { transition: background 0.6s; } }
113
+ /* behold#571: folded, whole lines only (fitFeatures); opened, it scrolls inside a bounded box. */
114
+ .r-feats { padding: 0.1em 1em 0.45em; border-bottom: 1px solid var(--rule); }
115
+ .r-feats-open .r-feats-list { max-height: 12em; overflow-y: auto; scrollbar-width: thin; }
116
+ .r-feats-label { padding: 0.3em 0 0.15em; }
117
+ .r-feats-list { display: flex; flex-wrap: wrap; gap: 0.3em 0.35em; align-items: center; }
118
+ .r-feats-list > [hidden] { display: none; }
119
+ .r-feats-product { font: 600 0.7em var(--font-mono); text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); border: 0; margin: 0 0.15em 0 0.4em; }
120
+ .r-feats-product:first-child { margin-left: 0; }
121
+ .r-feat, .r-feats-more { font: 0.8em var(--font-ui); line-height: 1.4; color: var(--fg); background: transparent; border: 1px solid var(--rule); border-radius: 999px; padding: 0.05em 0.6em; cursor: pointer; }
122
+ .r-feats-more { color: var(--pending); border-style: dashed; }
123
+ .r-feat:hover, .r-feat:focus-visible { border-color: var(--focus); background: var(--zebra-row); }
124
+ /*
125
+ * behold#571: the header in fixed boxes. The title, the card, the step
126
+ * line, and the hold's box each have a height that holds their text
127
+ * budget at 1600x1000 and 1920x1080 (terragucci#1061: the card's fields
128
+ * 120, 220 and 120 characters, the step 200); more scrolls inside the
129
+ * box, with a fade at the edge, so the panes below never move.
130
+ */
131
+ #bar { position: relative; display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 0.4em 0.9em; align-items: stretch;
132
+ padding: 0.45em 1em 0.5em; background: var(--bg); }
88
133
  #bar > .k-empty { grid-column: 1 / -1; }
89
- /* behold#571: the problem the demo solves, always on, across the bar's top. */
90
- .k-intro { grid-column: 1 / -1; margin: 0; font-size: 1em; line-height: 1.35; color: var(--fg); }
134
+ .k-left { display: grid; grid-template-rows: var(--k-title-h) var(--k-card-h) var(--k-step-h); gap: 0.35em; min-width: 0; }
135
+ :root { --k-title-h: 1.8em; --k-card-h: 6.2em; --k-step-h: 3.35em; }
136
+ .k-box { min-height: 0; overflow-y: auto; scrollbar-width: thin; background: var(--surface-box); border-radius: 6px; padding: 0.35em 0.7em; }
137
+ .k-box.k-more-below { -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 1.3em), transparent); mask-image: linear-gradient(to bottom, #000 calc(100% - 1.3em), transparent); }
138
+ .k-box.k-more-above { -webkit-mask-image: linear-gradient(to top, #000 calc(100% - 1.3em), transparent); mask-image: linear-gradient(to top, #000 calc(100% - 1.3em), transparent); }
139
+ .k-box.k-more-above.k-more-below { -webkit-mask-image: linear-gradient(to bottom, transparent, #000 1.3em, #000 calc(100% - 1.3em), transparent); mask-image: linear-gradient(to bottom, transparent, #000 1.3em, #000 calc(100% - 1.3em), transparent); }
140
+ .k-box-title { background: transparent; padding: 0.1em 0.1em 0; overflow: hidden; }
141
+ /* behold#571: between scenarios the card's box carries what the demo is about. */
142
+ .k-intro { margin: 0; font-size: 1.12em; line-height: 1.4; color: var(--fg); }
143
+ .k-intro-head { display: block; font: 600 0.62em var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-bottom: 0.15em; }
91
144
  .k-kicker { font: 600 0.58em var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-right: 0.9em; vertical-align: 0.2em; white-space: nowrap; }
92
145
  .k-cycle { color: var(--muted); font: 0.78em var(--font-mono); white-space: nowrap; }
93
- .k-title { margin: 0 0 0.2em; font-size: 1.35em; line-height: 1.2; }
146
+ .k-title { margin: 0; font-size: 1.3em; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
94
147
  /* behold#571: the scenario's card, three labelled rows under the title. */
95
- .k-about { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.08em 0.9em; align-items: baseline; margin: 0 0 0.35em; font-size: 0.88em; line-height: 1.25; }
148
+ .k-about { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.08em 0.9em; align-items: baseline; margin: 0; font-size: 0.88em; line-height: 1.25; }
96
149
  .k-about-label { font: 600 0.74em var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
97
150
  .k-about-text { margin: 0; color: var(--fg); }
98
151
  .k-muted { color: var(--muted); margin: 0.25em 0; }
99
- .k-step { border-left: 4px solid var(--pending); padding: 0.1em 0 0.1em 0.8em; margin: 0; font-size: 0.95em; line-height: 1.3; }
152
+ .k-step { border-left: 4px solid var(--pending); padding: 0 0 0 0.7em; margin: 0; font-size: 0.95em; line-height: 1.3; }
100
153
  .k-step-word { font: 600 0.72em var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-right: 0.7em; }
101
154
  .k-step-waiting { border-left-color: var(--foreign); }
102
155
  .k-step-failed, .k-step-stalled { border-left-color: var(--degraded); }
103
156
  .k-step-applied { border-left-color: var(--managed); }
104
157
  .k-step-reset { border-left-color: var(--neutral); }
105
- .k-right { display: grid; gap: 0.45em; align-content: start; }
158
+ /* The right column takes the left's height and never sets it: its hold box scrolls instead. */
159
+ .k-right { display: grid; grid-template-rows: auto auto minmax(0, 1fr); gap: 0.35em; min-width: 0; min-height: 0; contain: size; }
160
+ .k-where { padding-right: 13em; flex-wrap: nowrap; }
161
+ .k-next .k-cycle { margin-left: auto; }
106
162
  .k-where { display: flex; flex-wrap: wrap; gap: 0.35em 1em; align-items: center; }
107
163
  .k-strip { list-style: none; display: flex; flex-wrap: wrap; gap: 0.35em; padding: 0; margin: 0; }
108
164
  .k-stop { font: 0.82em var(--font-mono); padding: 0.25em 0.7em; border-radius: 999px; border: 1px solid var(--rule); color: var(--muted); }
@@ -114,6 +170,20 @@
114
170
  .k-action { font-family: var(--font-mono); }
115
171
  .k-when { color: var(--foreign); font-family: var(--font-mono); }
116
172
  .k-approve { border-left: 4px solid var(--foreign); padding-left: 0.8em; }
173
+ /* behold#571: "How this hold ends": four rows that light from the records. */
174
+ .k-ap-head { font: 600 0.7em var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 0.1em; }
175
+ .k-ap-head .k-ap-plan { text-transform: none; letter-spacing: 0; color: var(--fg); font-weight: 400; }
176
+ .k-ap-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.05em; }
177
+ .k-ap-row { display: grid; grid-template-columns: 1em 6.4em minmax(0, 1fr); gap: 0 0.35em; align-items: baseline; font-size: 0.84em; line-height: 1.28; }
178
+ .k-ap-mark { width: 0.75em; height: 0.75em; border-radius: 50%; border: 2px solid var(--muted); display: inline-block; align-self: start; margin-top: 0.25em; }
179
+ .k-ap-lit .k-ap-mark { background: var(--managed); border-color: var(--managed); }
180
+ .k-ap-going .k-ap-mark { border-color: var(--foreign); background: linear-gradient(90deg, var(--foreign) 50%, transparent 50%); }
181
+ .k-ap-label { font: 600 0.82em var(--font-mono); text-transform: uppercase; letter-spacing: 0.04em; color: var(--fg); }
182
+ .k-ap-dim .k-ap-label, .k-ap-dim .k-ap-text { color: var(--muted); }
183
+ .k-ap-facts { color: var(--muted); font-size: 0.92em; margin-left: 0.35em; }
184
+ .k-ap-bad { color: var(--degraded); }
185
+ .k-ap-row .k-command { grid-column: 3; margin: 0.1em 0; padding: 0.25em 0.6em; font-size: 0.92em; }
186
+ .k-ap .r-ann { font-size: 0.78em; }
117
187
  .k-approve p { margin: 0.15em 0; }
118
188
  .k-approve-gloss { color: var(--fg); font-size: 0.92em; }
119
189
  .k-approve-then { color: var(--muted); font-size: 0.92em; }
@@ -124,7 +194,7 @@
124
194
  #view-pane { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
125
195
  #view { display: block; width: 100%; flex: 1; min-height: 0; border: 0; background: var(--bg); }
126
196
  /* #571: the toggle between the two views, over the frame by the view's caption. */
127
- #views { display: flex; align-items: center; gap: 0.9em; padding: 0.45em 1em; border-bottom: 1px solid var(--rule); background: var(--panel); }
197
+ #views { display: flex; align-items: center; gap: 0.9em; padding: 0.45em 1em; border-bottom: 1px solid var(--rule); background: var(--surface-pane-a); border-radius: 6px 6px 0 0; }
128
198
  #views[hidden] { display: none; }
129
199
  .k-views { display: inline-flex; border: 1px solid var(--rule); border-radius: 999px; overflow: hidden; }
130
200
  .k-view { font: 600 0.85em var(--font-ui); color: var(--muted); background: transparent; border: 0; padding: 0.3em 0.95em; cursor: pointer; }
@@ -133,17 +203,82 @@
133
203
  .k-view-on { color: var(--bg); background: var(--pending); }
134
204
  .k-view-on:hover { color: var(--bg); }
135
205
  .k-view-note { color: var(--muted); font-size: 0.8em; }
136
- #foot { display: flex; flex-wrap: wrap; gap: 0.2em 1.6em; padding: 0.55em 1.6em; border-top: 1px solid var(--rule); background: var(--panel); font-size: 0.85em; }
206
+ #foot { display: flex; flex-wrap: wrap; gap: 0.2em 1.6em; padding: 0.5em 1.6em; border-top: 1px solid var(--rule); background: var(--surface-box); font-size: 0.85em; }
137
207
  .k-legend { color: var(--muted); flex-basis: 100%; }
208
+ /* behold#571: a tool's page. Its name (and logo where allowed) before the scenario, the replay's banner, the credit. */
209
+ .k-brand { display: inline-flex; align-items: center; gap: 0.35em; margin-right: 0.8em; color: var(--fg); text-decoration: none; font-weight: 700; vertical-align: 0.05em; }
210
+ .k-brand:hover .k-brand-name { text-decoration: underline; }
211
+ .k-brand-logo { width: 1.25em; height: 1.25em; }
212
+ .k-replay { grid-column: 1 / -1; margin: 0; padding: 0.2em 0.7em; padding-right: 16em; border-left: 4px solid var(--neutral); background: var(--surface-box); color: var(--fg); font-size: 0.92em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
213
+ /* behold#571: "What is this?" and the theme, at the header's top right, outside the boxes that redraw. */
214
+ #k-tools { position: absolute; top: 0.4em; right: 1em; z-index: 5; display: flex; gap: 0.7em; align-items: center; font-size: 0.8em; }
215
+ .k-what { font: inherit; color: var(--pending); background: transparent; border: 0; padding: 0.1em 0; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
216
+ #k-what-pop { position: absolute; top: 1.8em; right: 0; width: min(34em, calc(100vw - 32px)); padding: 0.7em 0.9em; background: var(--surface-pane-b); color: var(--fg); border: 1px solid var(--focus);
217
+ border-radius: 8px; box-shadow: 0 6px 24px color-mix(in srgb, var(--shadow) 70%, transparent); font-size: 1.15em; line-height: 1.45; }
218
+ #k-what-pop[hidden] { display: none; }
219
+ #k-what-pop p { margin: 0; }
220
+ .k-menu summary { cursor: pointer; color: var(--muted); list-style: none; }
221
+ .k-menu summary::-webkit-details-marker { display: none; }
222
+ .k-menu summary::after { content: " ▾"; }
223
+ .k-menu[open] summary { color: var(--fg); }
224
+ .k-menu-body { position: absolute; right: 0; top: 1.8em; padding: 0.5em; background: var(--surface-pane-b); border: 1px solid var(--rule); border-radius: 8px; }
225
+ .k-credit { color: var(--muted); flex-basis: 100%; }
226
+ .k-credit-link { color: var(--fg); }
227
+ .k-nograph-note { grid-column: 1 / -1; margin: 0; color: var(--muted); font-size: 0.88em; }
228
+ /* With no graph to show, the graph pane folds away and the runs and the log take its width. */
229
+ body.k-nograph #stage { grid-template-columns: minmax(15em, 22%) minmax(0, 1fr); }
230
+ body.k-nograph #view-pane { display: none; }
138
231
  .k-fact { color: var(--fg); }
139
- @media (max-width: 900px) { #bar { grid-template-columns: 1fr; } #stage { grid-template-columns: 1fr; } }
232
+ @media (max-width: 900px) and (min-width: 601px) { #bar { grid-template-columns: 1fr; } #stage, body.k-nograph #stage { grid-template-columns: 1fr; } }
233
+ /*
234
+ * behold#571: a phone. One column that scrolls as a page: the header
235
+ * (its boxes as tall as their text), the graph, then the runs and their
236
+ * logs behind "Runs and logs". Nothing wider than the screen.
237
+ */
238
+ @media (max-width: 600px) {
239
+ html, body { height: auto; overflow-x: hidden; overflow-y: auto; font-size: 14px; }
240
+ body { display: block; }
241
+ #bar { display: block; padding: 0.5em 16px 0.6em; }
242
+ #bar > * + * { margin-top: 0.45em; }
243
+ .k-left, .k-right { display: block; contain: none; }
244
+ .k-left > * + *, .k-right > * + * { margin-top: 0.4em; }
245
+ .k-box { height: auto; max-height: none; overflow: visible; -webkit-mask-image: none !important; mask-image: none !important; }
246
+ .k-title { white-space: normal; }
247
+ .k-where { padding-right: 0; }
248
+ .k-replay { padding-right: 0.7em; white-space: normal; }
249
+ #k-tools { position: static; justify-content: flex-end; margin: 0; padding: 0.4em 16px 0; }
250
+ #k-what-pop { right: 16px; left: 16px; width: auto; top: 2.2em; }
251
+ .k-ap-row { grid-template-columns: 1.1em 5.6em minmax(0, 1fr); }
252
+ #stage, body.k-nograph #stage { display: flex; flex-direction: column; padding: 0; gap: 0; }
253
+ #view-pane { order: 1; height: 64vh; }
254
+ body.k-nograph #view-pane { display: none; }
255
+ #k-runs-toggle { order: 2; display: block; margin: 0.6em 16px; padding: 0.6em 1em; font: 600 1em var(--font-ui); color: var(--fg); background: var(--surface-pane-b); border: 1px solid var(--rule); border-radius: 8px; cursor: pointer; text-align: left; }
256
+ #k-runs-toggle::after { content: " ▸"; }
257
+ body.k-runs-open #k-runs-toggle::after { content: " ▾"; }
258
+ #runs-side { order: 3; display: none; max-height: 50vh; border-radius: 0; }
259
+ #runs-main { order: 4; display: none; height: 85vh; border-radius: 0; }
260
+ body.k-runs-open #runs-side, body.k-runs-open #runs-main { display: flex; flex-direction: column; }
261
+ body.k-runs-open #runs-side { display: block; }
262
+ .r-log { margin-left: 0.4em; max-height: 60vh; }
263
+ .r-log-line { grid-template-columns: 2.4em 1fr; gap: 0.5em; }
264
+ .r-ann-note { grid-column: 1 / -1; }
265
+ #foot { padding: 0.5em 16px; }
266
+ }
140
267
  </style>
141
268
  </head>
142
269
  <body>
143
- <header id="bar" aria-live="polite"></header>
270
+ <div id="k-head">
271
+ <div id="k-tools">
272
+ <button type="button" class="k-what" aria-expanded="false" aria-controls="k-what-pop">What is this?</button>
273
+ <details class="k-menu"><summary>Theme</summary><div class="k-menu-body" id="k-theme"></div></details>
274
+ <div id="k-what-pop" role="dialog" aria-label="What is this?" hidden></div>
275
+ </div>
276
+ <header id="bar" aria-live="polite"></header>
277
+ </div>
144
278
  <div id="stage">
145
279
  <nav id="runs-side" aria-label="pipeline runs"></nav>
146
280
  <section id="runs-main" aria-live="polite"></section>
281
+ <button type="button" id="k-runs-toggle" aria-expanded="false">Runs and logs</button>
147
282
  <section id="view-pane">
148
283
  <div id="views" hidden></div>
149
284
  <iframe id="view" title="behold's view of the change"></iframe>
@@ -153,8 +288,16 @@
153
288
  <script type="module">
154
289
  import { initTheme } from "/theme.js";
155
290
  import { startKiosk } from "/kiosk.js";
291
+ import { pageTool } from "/kiosk-vendor.js";
156
292
  initTheme();
157
- startKiosk({ bar: document.getElementById("bar"), frame: document.getElementById("view"), foot: document.getElementById("foot"), side: document.getElementById("runs-side"), main: document.getElementById("runs-main"), views: document.getElementById("views") });
293
+ // behold#571: /<tool> serves this page with its tool in a meta tag; /kiosk has none.
294
+ startKiosk(
295
+ {
296
+ bar: document.getElementById("bar"), frame: document.getElementById("view"), foot: document.getElementById("foot"), side: document.getElementById("runs-side"), main: document.getElementById("runs-main"), views: document.getElementById("views"),
297
+ tools: { what: document.querySelector(".k-what"), pop: document.getElementById("k-what-pop"), theme: document.getElementById("k-theme"), runsToggle: document.getElementById("k-runs-toggle") },
298
+ },
299
+ { tool: pageTool(document) },
300
+ );
158
301
  </script>
159
302
  </body>
160
303
  </html>