getobsrv 0.7.2 → 0.9.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.
@@ -106,6 +106,7 @@
106
106
  --chrome-0: #141414;
107
107
  --chrome-1: #1c1c1c;
108
108
  --chrome-2: #262626;
109
+ --chrome-3: #3a3a3a;
109
110
  --line: #333333;
110
111
  --text-0: #ededed;
111
112
  --text-1: #8a8a8a;
@@ -131,66 +132,206 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
131
132
  .app { height: 100%; display: flex; flex-direction: column; }
132
133
  .muted { color: var(--text-1); }
133
134
  .warn { color: var(--warn); }
134
- .toolbar .warn { white-space: nowrap; }
135
-
136
- /* 44px matches TOOLBAR_H in src/main/ipc.ts, used until NativeSlot reports. */
137
- .toolbar {
138
- flex: 0 0 44px;
135
+ .chrome .warn { white-space: nowrap; }
136
+
137
+ /* Two strips. Browsing above; the controls that describe the simulated
138
+ screen below, on a darker ground so the rows read as separate registers.
139
+ 44 + 38 = 82 must equal TOOLBAR_H in src/main/ipc.ts. Pinned heights also
140
+ keep a late reflow from resizing the panes under NativeSlot's observer. */
141
+ .chrome { flex: 0 0 auto; }
142
+ .chrome-row {
143
+ box-sizing: border-box;
139
144
  display: flex;
140
145
  align-items: center;
141
146
  gap: 8px;
142
147
  padding: 0 10px;
143
- background: var(--chrome-1);
144
148
  border-bottom: 1px solid var(--line);
145
149
  }
146
- .toolbar button {
150
+ .chrome-browse { height: 44px; background: var(--chrome-1); }
151
+ .chrome-screen { height: 38px; background: var(--chrome-0); }
152
+ .chrome-spacer { flex: 1 1 auto; }
153
+
154
+ /* No blanket `button` rule here, ever. The old `.toolbar button { width:
155
+ 26px }` was specificity (0,1,1) and silently clipped the update button to
156
+ "v0."; every control now sizes itself. */
157
+ .icon-button {
158
+ flex: 0 0 auto;
159
+ width: 30px;
160
+ height: 30px;
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
147
164
  background: var(--chrome-2);
148
165
  color: var(--text-0);
149
166
  border: 1px solid var(--line);
150
- border-radius: 4px;
151
- width: 26px;
152
- height: 24px;
167
+ border-radius: 5px;
153
168
  cursor: pointer;
154
169
  }
155
- .toolbar select {
156
- background: var(--chrome-2);
157
- color: var(--text-0);
158
- border: 1px solid var(--line);
159
- border-radius: 4px;
160
- height: 24px;
161
- }
162
- .url-form { flex: 1 1 auto; min-width: 120px; }
170
+
171
+ .url-form { flex: 1 1 auto; min-width: 160px; }
163
172
  .url-form input {
164
173
  width: 100%;
165
- height: 24px;
174
+ height: 30px;
166
175
  box-sizing: border-box;
167
- padding: 0 8px;
176
+ padding: 0 10px;
177
+ font-size: 12.5px;
168
178
  background: var(--field);
169
179
  color: var(--text-0);
170
180
  border: 1px solid var(--line);
171
- border-radius: 4px;
181
+ border-radius: 5px;
172
182
  }
173
183
  .url-form input[readonly] { color: var(--text-1); }
184
+
185
+ .status-cluster { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; font-size: 10px; }
174
186
  .badge-error {
175
187
  color: var(--error);
176
188
  border: 1px solid var(--error);
177
189
  border-radius: 4px;
178
- padding: 1px 6px;
190
+ padding: 2px 6px;
191
+ font-family: var(--mono);
179
192
  font-variant-numeric: tabular-nums;
180
193
  }
181
- .pixel-exact { display: flex; align-items: center; gap: 4px; white-space: nowrap; }
182
- /* The checked state would otherwise take the OS accent colour. */
183
- .toolbar input[type='checkbox'] { accent-color: var(--text-0); }
194
+ /* An update is neither a warning nor an error, so it carries no colour. */
195
+ .update-button {
196
+ flex: 0 0 auto;
197
+ height: 30px;
198
+ padding: 0 10px;
199
+ white-space: nowrap;
200
+ font-family: var(--mono);
201
+ font-size: 11.5px;
202
+ font-variant-numeric: tabular-nums;
203
+ background: var(--chrome-2);
204
+ color: var(--text-0);
205
+ border: 1px solid var(--line);
206
+ border-radius: 5px;
207
+ cursor: pointer;
208
+ }
209
+
210
+ /* Our surface, the platform's popup: the real select sits transparent on
211
+ top, keeping the native menu, keyboard handling and Playwright's
212
+ `selectOption` working unchanged. */
213
+ .select-shell {
214
+ position: relative;
215
+ flex: 0 0 auto;
216
+ display: inline-flex;
217
+ align-items: center;
218
+ height: 30px;
219
+ box-sizing: border-box;
220
+ padding: 0 26px 0 9px;
221
+ font-size: 11.5px;
222
+ white-space: nowrap;
223
+ background: var(--chrome-2);
224
+ color: var(--text-0);
225
+ border: 1px solid var(--line);
226
+ border-radius: 5px;
227
+ }
228
+ .select-shell select {
229
+ position: absolute;
230
+ inset: 0;
231
+ width: 100%;
232
+ height: 100%;
233
+ opacity: 0;
234
+ appearance: none;
235
+ cursor: pointer;
236
+ }
237
+ .select-shell .select-chevron {
238
+ position: absolute;
239
+ right: 7px;
240
+ display: flex;
241
+ color: var(--text-1);
242
+ pointer-events: none;
243
+ }
244
+
245
+ /* Segmented groups. Pressed is a fill step and weight, never hue. */
246
+ .segmented {
247
+ flex: 0 0 auto;
248
+ display: inline-flex;
249
+ height: 30px;
250
+ /* A `div`, unlike a `button`, does not get the UA's border-box: without
251
+ this the 1px border makes the group 32px and it sits 1px proud of every
252
+ other 30px control in the row. */
253
+ box-sizing: border-box;
254
+ border: 1px solid var(--line);
255
+ border-radius: 5px;
256
+ overflow: hidden;
257
+ }
258
+ .segmented button {
259
+ height: 100%;
260
+ padding: 0 11px;
261
+ font-size: 11.5px;
262
+ background: var(--chrome-2);
263
+ color: var(--text-1);
264
+ border: 0;
265
+ border-right: 1px solid var(--line);
266
+ border-radius: 0;
267
+ cursor: pointer;
268
+ }
269
+ .segmented button:last-child { border-right: 0; }
270
+ .segmented button[aria-pressed='true'] { background: var(--chrome-3); color: var(--text-0); }
184
271
 
185
- /* Focus is a 1px inset neutral ring (the style spec's "weight and a 1px
186
- inset ring"), never Chromium's accent-coloured outline. Pointer focus on
187
- buttons and selects shows nothing; keyboard focus (and any focus in a
188
- text field) shows the ring. */
189
- .toolbar :is(button, select, input):focus { outline: none; }
190
- .toolbar :is(button, select, input):focus-visible {
272
+ /* Right-aligned deliberately: the native pane is an OS-level WebContentsView
273
+ that covers renderer paint, so a menu reaching the left half of the window
274
+ would be invisible. 200px against a 900px minWidth always fits the target
275
+ pane. */
276
+ .overflow { position: relative; flex: 0 0 auto; }
277
+ .overflow-menu {
278
+ position: absolute;
279
+ top: calc(100% + 4px);
280
+ right: 0;
281
+ z-index: 10;
282
+ width: 200px;
283
+ padding: 5px 0;
284
+ font-size: 11.5px;
285
+ background: var(--chrome-2);
286
+ border: 1px solid var(--line);
287
+ border-radius: 6px;
288
+ }
289
+ .menu-row {
290
+ display: flex;
291
+ align-items: center;
292
+ gap: 8px;
293
+ width: 100%;
294
+ box-sizing: border-box;
295
+ height: 30px;
296
+ padding: 0 11px;
297
+ text-align: left;
298
+ background: none;
299
+ color: var(--text-0);
300
+ border: 0;
301
+ border-radius: 0;
302
+ cursor: pointer;
303
+ }
304
+ .menu-row:hover { background: var(--chrome-3); }
305
+ /* Which drawer is open. The fill step is the chrome's one pressed idiom,
306
+ shared with `.segmented`; `:hover` is the same fill, so the pressed row also
307
+ carries a 2px inset rule down its leading edge. That marker is the part that
308
+ survives hover — hovering any row fills it, but only the open drawer's row
309
+ keeps the rule — and it is the same neutral weight the surround control uses
310
+ to mark its selection. No hue, here or anywhere else in the chrome. */
311
+ .menu-row[aria-pressed='true'] {
312
+ background: var(--chrome-3);
313
+ box-shadow: inset 2px 0 0 var(--text-0);
314
+ }
315
+ .menu-sep { height: 1px; margin: 5px 0; background: var(--line); }
316
+ /* Sized to the 16px icons the other rows lead with, and stripped of the UA's
317
+ own margins, so every label in the menu starts at the same x — a checkbox
318
+ row and an icon row otherwise indent differently. */
319
+ .overflow-menu input[type='checkbox'] {
320
+ accent-color: var(--text-0);
321
+ flex: 0 0 auto;
322
+ width: 16px;
323
+ height: 16px;
324
+ margin: 0;
325
+ }
326
+
327
+ /* Focus is a 1px inset neutral ring, never Chromium's accent outline. */
328
+ .chrome :is(button, select, input):focus { outline: none; }
329
+ .chrome :is(button, select, input):focus-visible {
191
330
  outline: 1px solid var(--text-1);
192
331
  outline-offset: -1px;
193
332
  }
333
+ /* The real select is transparent, so its ring must land on the shell. */
334
+ .select-shell:has(select:focus-visible) { outline: 1px solid var(--text-1); outline-offset: -1px; }
194
335
 
195
336
  .panes { flex: 1 1 auto; display: flex; min-height: 0; }
196
337
  .pane {
@@ -232,11 +373,29 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
232
373
  }
233
374
  .pane-footer .role { color: var(--text-0); letter-spacing: 0.08em; }
234
375
 
235
- /* Segmented surround control. Active state is weight and a border, not hue. */
236
- .surround-control { display: flex; border: 1px solid var(--line); border-radius: 4px; }
376
+ /* Segmented surround control: the same 30px border-box as `.segmented` and
377
+ `.select-shell`, so the screen row has one hit-target rhythm. `box-sizing`
378
+ for the same reason `.segmented` needs it — a `div` gets no border-box from
379
+ the UA, so the 1px border would otherwise push the group to 32px.
380
+
381
+ The swatch stays 12px: the swatch is the affordance, the button around it is
382
+ just the target. The pressed state stays an inset `--text-0` ring, and is
383
+ the one place the chrome does not use the `--chrome-3` fill step — a fill
384
+ ringing a 12px swatch competes with the swatch for the eye, and `--chrome-3`
385
+ lands two steps from the graphite swatch itself. This is the one control
386
+ whose whole job is judging a tint, so the marker stays off the tint. */
387
+ .surround-control {
388
+ box-sizing: border-box;
389
+ flex: 0 0 auto;
390
+ display: inline-flex;
391
+ height: 30px;
392
+ border: 1px solid var(--line);
393
+ border-radius: 5px;
394
+ overflow: hidden;
395
+ }
237
396
  .surround-control button {
238
- width: 22px;
239
- height: 22px;
397
+ width: 28px;
398
+ height: 100%;
240
399
  border: 0;
241
400
  border-right: 1px solid var(--line);
242
401
  border-radius: 0;
@@ -247,28 +406,25 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
247
406
  .surround-control button[aria-pressed='true'] { box-shadow: inset 0 0 0 2px var(--text-0); }
248
407
  .surround-swatch { display: block; width: 12px; height: 12px; margin: 0 auto; }
249
408
 
409
+ /* Nothing sits to the target pane's left in solo view, so the divider goes. */
410
+ .panes[data-panes='target'] .target-pane { border-left: 0; }
411
+
250
412
  /* Numbers never jitter as a slider moves. */
251
413
  .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
252
414
 
253
- /* An open drawer's button: weight and a 1px border, not hue. */
254
- .toolbar :is(.toggle-panel, .toggle-settings, .agent-toggle)[aria-pressed='true'] {
255
- border-color: var(--text-0);
256
- background: var(--chrome-1);
257
- }
258
-
259
- /* Agent control: same neutral chrome as every other toggle; the activity
260
- badge is text-weight only — an agent driving the window is a status, not
261
- an alert. */
262
- .toolbar .agent-toggle { width: auto; padding: 0 8px; white-space: nowrap; }
415
+ /* Agent control opens a loopback server, so the chip persists while it is
416
+ enabled; recent activity is a brighter text weight, not a colour. */
263
417
  .agent-activity {
418
+ flex: 0 0 auto;
264
419
  color: var(--text-1);
265
420
  border: 1px solid var(--line);
266
421
  border-radius: 4px;
267
- padding: 1px 6px;
268
- font-size: 11px;
269
- letter-spacing: 0.5px;
422
+ padding: 2px 7px;
423
+ font-size: 10px;
424
+ letter-spacing: 0.08em;
270
425
  white-space: nowrap;
271
426
  }
427
+ .agent-activity.active { color: var(--text-0); border-color: var(--text-0); }
272
428
 
273
429
  /* Drawers sit beside the panes, never over them: the native WebContentsView is
274
430
  an OS-level overlay and would cover anything painted on top of it. */
@@ -363,7 +519,6 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
363
519
  }
364
520
  .strip button:focus { outline: none; }
365
521
  .strip button:focus-visible { outline: 1px solid var(--text-1); outline-offset: 1px; }
366
- .toolbar .close-image { width: auto; padding: 0 8px; }
367
522
  /* `safe`: a file wider than the pane scrolls from its left edge instead of
368
523
  losing it off-screen. */
369
524
  .image-pane .pane-body { display: flex; align-items: flex-start; justify-content: safe center; }
@@ -438,25 +593,10 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
438
593
  .stall button:focus { outline: none; }
439
594
  .stall button:focus-visible { outline: 1px solid var(--text-1); outline-offset: 1px; }
440
595
 
441
- /* v1.1 fit & pan. The 1:1/Fit segmented control follows the surround
442
- control's grammar: active state is weight and an inset ring, never hue. */
443
- .view-control { display: flex; border: 1px solid var(--line); border-radius: 4px; }
444
- .view-control button {
445
- width: auto;
446
- height: 22px;
447
- padding: 0 8px;
448
- border: 0;
449
- border-right: 1px solid var(--line);
450
- border-radius: 0;
451
- background: var(--chrome-2);
452
- font-variant-numeric: tabular-nums;
453
- cursor: pointer;
454
- }
455
- .view-control button:last-child { border-right: 0; }
456
- .view-control button[aria-pressed='true'] {
457
- box-shadow: inset 0 0 0 1px var(--text-0);
458
- font-weight: 600;
459
- }
596
+ /* v1.1 fit & pan. The 1:1/Fit control is a `Segmented`, so `.segmented` is
597
+ the whole of its styling the old `.view-control button` rules lived here,
598
+ and being (0,1,1) and later in the file they beat `.segmented button` and
599
+ split the two groups apart. Nothing about 1:1/Fit is control-specific. */
460
600
 
461
601
  /* The overview invites the jump-to-1:1 click; the pan chords (middle drag,
462
602
  Option+drag) show the grab affordances. Cursors only — no overlay may sit
@@ -478,18 +618,6 @@ html, body, #root { margin: 0; height: 100%; background: var(--chrome-0); color:
478
618
  .browser-notice p { margin: 0.75rem 0 0; color: var(--text-1); }
479
619
  .browser-notice code { font-family: var(--mono); }
480
620
 
481
- /* An update is neither a warning nor an error, so it carries no colour: the
482
- only chromatic pixels in this chrome stay reserved for real attention. */
483
- /* `.toolbar button` is (0,1,1) and pins every button to a 26px square, so this
484
- needs two classes to outrank it — a bare `.update-button` renders as "v0.". */
485
- .toolbar .update-button {
486
- font-family: var(--mono);
487
- font-variant-numeric: tabular-nums;
488
- white-space: nowrap;
489
- width: auto;
490
- flex: 0 0 auto;
491
- padding: 0 8px;
492
- }
493
621
  .version-block { margin: 8px 0; }
494
622
  .version-row {
495
623
  display: flex;