xtralab 0.12.5 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtralab",
3
- "version": "0.12.5",
3
+ "version": "0.13.0",
4
4
  "description": "An opinionated JupyterLab meta-package that bundles a curated set of extensions, ships a path-first file browser, renders jupyterlab-git's text, notebook and image diffs with its own viewers, and applies a quieter default workspace configuration.",
5
5
  "keywords": [
6
6
  "jupyter",
package/style/base.css CHANGED
@@ -147,7 +147,7 @@
147
147
  padding: 2px 6px;
148
148
  background-color: var(--jp-layout-color1);
149
149
  border: 1px solid var(--jp-border-color2);
150
- border-radius: 2px;
150
+ border-radius: 6px;
151
151
  color: var(--jp-ui-font-color1);
152
152
  font-family: var(--jp-ui-font-family);
153
153
  font-size: var(--jp-ui-font-size1);
@@ -0,0 +1,1209 @@
1
+ /*
2
+ * The chrome layer: a token-driven modernization pass over stock JupyterLab
3
+ * and Lumino chrome, so the app reads as a quiet native window rather than a
4
+ * paneled web app.
5
+ *
6
+ * The language, in one place:
7
+ * - one surface, separated by hairlines (--jp-border-color2), not the stock
8
+ * grid of grey-400 borders;
9
+ * - a radius scale: controls ~5-6px, popovers 8-10px, dialogs 12px;
10
+ * - soft large-blur shadows rebuilt from each theme's own shadow pieces;
11
+ * - state washes mixed from the theme's foreground (color-mix over
12
+ * --jp-ui-font-color1) instead of opaque layout-color blocks;
13
+ * - 100-150ms ease on hover state changes;
14
+ * - frosted translucency on transient overlays (menus, palette, omnibox).
15
+ *
16
+ * Two ground rules keep this safe:
17
+ * 1. Every color derives from the active theme's --jp-* tokens (or a
18
+ * color-mix over them), so the layer composes with JupyterLab
19
+ * Light/Dark and both Pierre themes. Theme-conditional rules key off
20
+ * body[data-jp-theme-light].
21
+ * 2. Lumino positions panels, tab bars, and menus with pixel math, so
22
+ * rules stick to paint-only properties (color, background,
23
+ * border-color, border-radius, box-shadow, opacity, transition).
24
+ * Where a stock border exists, only its color changes — widths stay.
25
+ *
26
+ * Token overrides live on `body`, not :root: themes define their tokens on
27
+ * :root in stylesheets loaded after this one, and inheritance from body
28
+ * beats :root regardless of load order.
29
+ */
30
+
31
+ /* stylelint-disable no-descending-specificity */
32
+
33
+ /* -----------------------------------------------------------------------------
34
+ | Design tokens
35
+ |---------------------------------------------------------------------------- */
36
+
37
+ body {
38
+ /* Controls-tier corner radius. Every styled button/input/select and the
39
+ FAST toolkit (which forwards this token to its shadow-DOM controls via
40
+ applyJupyterTheme -> controlCornerRadius) follows. */
41
+ --jp-border-radius: 6px;
42
+
43
+ /* Elevation ramp: fewer layers, larger blur, negative spread. Built from
44
+ the theme's own shadow color pieces, so each theme keeps its shadow
45
+ character (including Pierre light's deliberately faint shadows). */
46
+ --jp-elevation-z1: 0 1px 2px var(--jp-shadow-ambient-color);
47
+ --jp-elevation-z2:
48
+ 0 1px 3px var(--jp-shadow-penumbra-color),
49
+ 0 1px 2px var(--jp-shadow-ambient-color);
50
+ --jp-elevation-z4:
51
+ 0 4px 12px -2px var(--jp-shadow-penumbra-color),
52
+ 0 1px 3px var(--jp-shadow-ambient-color);
53
+ --jp-elevation-z6:
54
+ 0 8px 24px -6px var(--jp-shadow-umbra-color),
55
+ 0 2px 6px -2px var(--jp-shadow-ambient-color);
56
+ --jp-elevation-z8:
57
+ 0 10px 28px -6px var(--jp-shadow-umbra-color),
58
+ 0 3px 8px -3px var(--jp-shadow-ambient-color);
59
+ --jp-elevation-z12:
60
+ 0 14px 32px -8px var(--jp-shadow-umbra-color),
61
+ 0 4px 10px -4px var(--jp-shadow-ambient-color);
62
+ --jp-elevation-z16:
63
+ 0 18px 40px -10px var(--jp-shadow-umbra-color),
64
+ 0 5px 12px -5px var(--jp-shadow-ambient-color);
65
+ --jp-elevation-z20:
66
+ 0 24px 48px -12px var(--jp-shadow-umbra-color),
67
+ 0 6px 16px -6px var(--jp-shadow-ambient-color);
68
+ --jp-elevation-z24:
69
+ 0 28px 56px -14px var(--jp-shadow-umbra-color),
70
+ 0 8px 20px -8px var(--jp-shadow-ambient-color);
71
+
72
+ /* Toolbars separate with their existing border-bottom alone; the stock
73
+ omnidirectional 2px smudge shadow under every toolbar goes. */
74
+ --jp-toolbar-box-shadow: none;
75
+ --jp-toolbar-border-color: var(--jp-border-color2);
76
+
77
+ /* Inputs: rest on the theme's border ramp instead of the heavy
78
+ --jp-inverse-border-color (#757575 in both stock JupyterLab themes),
79
+ and focus with a soft outer ring instead of the inset blue glow. The
80
+ border-color swap to --jp-input-active-border-color that ships with
81
+ every stock :focus rule stays, giving the border + halo combo. */
82
+ --jp-input-border-color: var(--jp-border-color1);
83
+ --jp-input-box-shadow: 0 0 0 3px
84
+ color-mix(
85
+ in srgb,
86
+ var(--jp-input-active-border-color, var(--jp-brand-color1)) 22%,
87
+ transparent
88
+ );
89
+
90
+ /* Focused notebook/console cell: same outer-halo language, derived from
91
+ the theme's active cell border color (brand in all shipped themes). */
92
+ --jp-cell-editor-box-shadow: 0 0 0 3px
93
+ color-mix(
94
+ in srgb,
95
+ var(--jp-cell-editor-active-border-color, var(--jp-brand-color1)) 18%,
96
+ transparent
97
+ );
98
+
99
+ /* The stock JupyterLab themes color the ON state of switches ORANGE
100
+ (md-orange-900/700) — point it at the brand color instead (a no-op for
101
+ the Pierre themes). accent-color inherits into every native
102
+ checkbox/radio (dialogs, Settings editor, search filters). */
103
+ --jp-switch-true-position-color: var(--jp-brand-color1);
104
+
105
+ accent-color: var(--jp-brand-color1);
106
+
107
+ /* One selection language: brand-derived focused selection (JupyterLab
108
+ Light still ships a 2010-era solid lavender), neutral grey-out when
109
+ unfocused, light brand wash for multi-selected cells. Alpha values
110
+ layer correctly over the active-line highlight. */
111
+ --jp-editor-selected-focused-background: color-mix(
112
+ in srgb,
113
+ var(--jp-brand-color1) 22%,
114
+ transparent
115
+ );
116
+ --jp-editor-selected-background: color-mix(
117
+ in srgb,
118
+ var(--jp-ui-font-color1) 12%,
119
+ transparent
120
+ );
121
+ --jp-notebook-multiselected-color: color-mix(
122
+ in srgb,
123
+ var(--jp-brand-color1) 12%,
124
+ transparent
125
+ );
126
+
127
+ /* Dataframe row hover: brand wash instead of per-theme ad-hoc blues
128
+ (solid baby-blue in JupyterLab Light). */
129
+ --jp-rendermime-table-row-hover-background: color-mix(
130
+ in srgb,
131
+ var(--jp-brand-color1) 10%,
132
+ transparent
133
+ );
134
+
135
+ /* System monospace (SF Mono on macOS via ui-monospace), falling back to
136
+ the exact stock stack elsewhere. The prompt font follows so In[n]/Out[n]
137
+ match the editor. The terminal font is a JS setting, not CSS. */
138
+ --jp-code-font-family:
139
+ ui-monospace, 'SF Mono', sfmono-regular, menlo, consolas,
140
+ 'DejaVu Sans Mono', monospace;
141
+ --jp-cell-prompt-font-family: var(--jp-code-font-family);
142
+ }
143
+
144
+ /*
145
+ * Light themes draw the chrome skeleton in a heavy mid-grey
146
+ * (--jp-border-color1 is #bdbdbd in JupyterLab Light). Step it down to the
147
+ * theme's own next ramp value for the hairline look. Dark themes keep their
148
+ * stronger line: shadows carry less depth information there, so color1
149
+ * stays for edge definition.
150
+ */
151
+ body[data-jp-theme-light='true'] {
152
+ --jp-border-color1: var(--jp-border-color2);
153
+ }
154
+
155
+ /* The Pierre themes define neither focus-outline token, so stock
156
+ :focus-visible rules collapse to browser-default outlines there. Backfill
157
+ with the values JupyterLab Light uses. Scoped to the Pierre themes only:
158
+ JupyterLab Dark defines its own deliberately lighter #38a0f5 focus color,
159
+ which an unscoped body-level token would silently override. */
160
+ body[data-jp-theme-name='Pierre Light'],
161
+ body[data-jp-theme-name='Pierre Dark'] {
162
+ --jp-focus-outline-color: var(--jp-brand-color1);
163
+ --jp-focus-outline-width: 2px;
164
+ }
165
+
166
+ /*
167
+ * Slim quiet scrollbars everywhere. scrollbar-color inherits (crossing
168
+ * shadow-DOM boundaries), so the body rule recolors every scroll surface;
169
+ * scrollbar-width does NOT inherit, hence the separate descendant rule.
170
+ * In Chromium a non-auto value for either property disables
171
+ * ::-webkit-scrollbar styling on that element, which is also why the
172
+ * carve-outs below reset both to `auto`. body[data-jp-theme-light] matches
173
+ * every theme (the attribute is always present) and out-specifies core's
174
+ * optional [data-jp-theme-scrollbars='true'] rule. Elements that set their
175
+ * own scrollbar-color (e.g. core's .jp-scrollbar-tiny) keep it — a direct
176
+ * declaration always beats an inherited value.
177
+ */
178
+ body[data-jp-theme-light] {
179
+ scrollbar-color: color-mix(in srgb, var(--jp-ui-font-color1) 28%, transparent)
180
+ transparent;
181
+ }
182
+
183
+ /* The universal selector does not pierce shadow DOM, so @pierre internals
184
+ are untouched by the width rule. */
185
+ body[data-jp-theme-light],
186
+ body[data-jp-theme-light] * {
187
+ scrollbar-width: thin;
188
+ }
189
+
190
+ /* Carve-out: the dock tab strip keeps its hand-built 2px webkit scrollbar
191
+ (style/tabs.css); element-level `auto` re-enables those rules. */
192
+ .lm-DockPanel-tabBar .lm-TabBar-content {
193
+ scrollbar-width: auto;
194
+ scrollbar-color: auto;
195
+ }
196
+
197
+ /* Carve-out: @pierre/trees (file browser) and @pierre/diffs (git diffs)
198
+ build their own hover-revealed webkit scrollbars inside shadow roots —
199
+ including a scrollbar-measuring element that feeds the trees gutter
200
+ width. Resetting the hosts to `auto` makes their shadow trees inherit
201
+ `auto` again, re-enabling both. The body[...] prefix out-specifies the
202
+ universal width rule above. */
203
+ body[data-jp-theme-light] file-tree-container,
204
+ body[data-jp-theme-light] diffs-container {
205
+ scrollbar-width: auto;
206
+ scrollbar-color: auto;
207
+ }
208
+
209
+ /* -----------------------------------------------------------------------------
210
+ | Window chrome: seams, menu bar, activity strips, status bar, splitters
211
+ |---------------------------------------------------------------------------- */
212
+
213
+ /* Structural hairlines: recolor the shell's skeleton borders (widths stay). */
214
+ #jp-top-panel {
215
+ border-bottom-color: var(--jp-border-color2);
216
+ }
217
+
218
+ .jp-LabShell[data-shell-mode='single-document'] #jp-menu-panel {
219
+ border-bottom-color: var(--jp-border-color2);
220
+ }
221
+
222
+ .jp-SideArea[data-side='left'] {
223
+ border-right-color: var(--jp-border-color2);
224
+ }
225
+
226
+ .jp-SideArea[data-side='right'] {
227
+ border-left-color: var(--jp-border-color2);
228
+ }
229
+
230
+ /*
231
+ * Re-assert the sidebar width floor over inline styles. Stock intends
232
+ * --jp-sidebar-min-width as the floor for sidebar stack children, but a
233
+ * widget moved into a sidebar (Move Widget To, or a drag) keeps the tiny
234
+ * inline min-width Lumino wrote while it lived in the dock — and inline
235
+ * beats the stylesheet, so the floor never engages for it. Combined with
236
+ * the shell saving the raw split sizes while a sidebar is collapsed
237
+ * (collapsed = ~0, unguarded upstream, unlike the down area's
238
+ * _lastDownAreaSize), a restored workspace then expands that sidebar to a
239
+ * 1px sliver. !important is the one thing that outranks an inline style;
240
+ * with the floor restored, even a zero saved size expands to a usable
241
+ * panel.
242
+ */
243
+ #jp-left-stack > .lm-Widget,
244
+ #jp-right-stack > .lm-Widget {
245
+ min-width: var(--jp-sidebar-min-width) !important;
246
+ }
247
+
248
+ #jp-down-stack {
249
+ border-bottom-color: var(--jp-border-color2);
250
+ }
251
+
252
+ /* Borders framing each open document/panel in the dock. */
253
+ .lm-Widget.lm-DockPanel-widget,
254
+ .lm-TabPanel-stackedPanel.lm-TabPanel-stackedPanel {
255
+ border-color: var(--jp-border-color2);
256
+ }
257
+
258
+ /* The 5px gutters between tiled editors show whatever paints behind the
259
+ dock panel — stock falls through to the body's layout-color3 (#bdbdbd in
260
+ JupyterLab Light). A quiet surface makes split views separate with a
261
+ soft seam instead of a dark bar. */
262
+ #jp-main-dock-panel {
263
+ background: var(--jp-layout-color2);
264
+ }
265
+
266
+ /*
267
+ * Menu bar: stock hover is an opaque grey block, and the OPEN item paints
268
+ * an opaque fill + 1px side borders + z6 shadow to fake a "tab connected
269
+ * to the menu". Rounded translucent highlights instead; the transparent
270
+ * 1px borders Lumino reserves keep their widths, so nothing shifts.
271
+ */
272
+ .lm-MenuBar-item {
273
+ border-radius: 5px;
274
+ transition: background-color 120ms ease;
275
+ }
276
+
277
+ .jp-ThemedContainer .lm-MenuBar-item.lm-mod-active {
278
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 7%, transparent);
279
+ }
280
+
281
+ .jp-ThemedContainer .lm-MenuBar.lm-mod-active .lm-MenuBar-item.lm-mod-active {
282
+ color: var(--jp-ui-font-color0);
283
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 11%, transparent);
284
+ border-left-color: transparent;
285
+ border-right-color: transparent;
286
+ box-shadow: none;
287
+ }
288
+
289
+ .jp-LabShell[data-shell-mode='single-document']
290
+ .lm-MenuBar.lm-mod-active
291
+ .lm-MenuBar-item.lm-mod-active {
292
+ border-top-color: transparent;
293
+ }
294
+
295
+ /*
296
+ * Activity strips (left/right sidebar tab bars, in either orientation) and
297
+ * the down-area tab bar: stock draws them as bordered layout-color2 bands
298
+ * with separators between tabs and an opaque current tab — a classic
299
+ * tab-widget look. Flatten onto the window surface: hairline seams, muted
300
+ * icons that wake on hover, translucent washes, and a 2px brand accent on
301
+ * the current tab's outer edge. All separator overrides change border
302
+ * COLOR only, so the 1px widths Lumino measured stay.
303
+ */
304
+ .jp-SideBar.lm-TabBar,
305
+ #jp-down-stack .lm-TabBar {
306
+ background: var(--jp-layout-color1);
307
+ }
308
+
309
+ /* Hairline between the strip and its neighbor, all four placements. */
310
+ .jp-SideBar.lm-TabBar.jp-mod-left::after {
311
+ border-right-color: var(--jp-border-color2);
312
+ }
313
+
314
+ .jp-SideBar.lm-TabBar.jp-mod-right::after {
315
+ border-left-color: var(--jp-border-color2);
316
+ }
317
+
318
+ .jp-SideBar.lm-TabBar[data-side='top'] {
319
+ border-bottom-color: var(--jp-border-color2);
320
+ }
321
+
322
+ .jp-SideBar.lm-TabBar[data-side='bottom'] {
323
+ border-top-color: var(--jp-border-color2);
324
+ }
325
+
326
+ /* Separators off — vertical orientation… */
327
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
328
+ .lm-TabBar-tab
329
+ + .lm-TabBar-tab,
330
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
331
+ .lm-TabBar-tab.lm-mod-current
332
+ + .lm-TabBar-tab,
333
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
334
+ .lm-TabBar-tab
335
+ + .lm-TabBar-tab.lm-mod-current {
336
+ border-top-color: transparent;
337
+ }
338
+
339
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
340
+ .lm-TabBar-tab.lm-mod-current:last-child {
341
+ border-bottom-color: transparent;
342
+ }
343
+
344
+ /* …and horizontal orientation. */
345
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
346
+ .lm-TabBar-tab
347
+ + .lm-TabBar-tab,
348
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
349
+ .lm-TabBar-tab.lm-mod-current
350
+ + .lm-TabBar-tab,
351
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
352
+ .lm-TabBar-tab
353
+ + .lm-TabBar-tab.lm-mod-current {
354
+ border-left-color: transparent;
355
+ }
356
+
357
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
358
+ .lm-TabBar-tab.lm-mod-current:last-child {
359
+ border-right-color: transparent;
360
+ }
361
+
362
+ /* The current tab's "internal border override" pseudo-element paints an
363
+ opaque frame over the strip's edge hairline; keep the hairline running
364
+ continuously instead. */
365
+ .jp-SideBar .lm-TabBar-tab.lm-mod-current::after {
366
+ border-color: transparent;
367
+ }
368
+
369
+ /* Resting / hover / current fills. */
370
+ .jp-SideBar .lm-TabBar-tab:not(.lm-mod-current),
371
+ #jp-down-stack .lm-TabBar-tab:not(.lm-mod-current) {
372
+ background: transparent;
373
+ transition: background-color 120ms ease;
374
+ }
375
+
376
+ .jp-SideBar .lm-TabBar-tab:hover:not(.lm-mod-current),
377
+ #jp-down-stack .lm-TabBar-tab:hover:not(.lm-mod-current) {
378
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 6%, transparent);
379
+ }
380
+
381
+ .jp-SideBar .lm-TabBar-tab.lm-mod-current {
382
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 4%, transparent);
383
+ }
384
+
385
+ /* Current-tab accent on the strip's outer edge (VS Code activity bar). */
386
+ .jp-SideBar.jp-mod-left .lm-TabBar-tab.lm-mod-current {
387
+ box-shadow: inset 2px 0 0 0 var(--jp-brand-color1);
388
+ }
389
+
390
+ .jp-SideBar.jp-mod-right .lm-TabBar-tab.lm-mod-current {
391
+ box-shadow: inset -2px 0 0 0 var(--jp-brand-color1);
392
+ }
393
+
394
+ .jp-SideBar[data-side='top'] .lm-TabBar-tab.lm-mod-current {
395
+ box-shadow: inset 0 -2px 0 0 var(--jp-brand-color1);
396
+ }
397
+
398
+ .jp-SideBar[data-side='bottom'] .lm-TabBar-tab.lm-mod-current {
399
+ box-shadow: inset 0 2px 0 0 var(--jp-brand-color1);
400
+ }
401
+
402
+ /* Muted icons that wake on hover/selection. */
403
+ .jp-SideBar .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
404
+ opacity: 0.7;
405
+ transition: opacity 120ms ease;
406
+ }
407
+
408
+ .jp-SideBar .lm-TabBar-tab:hover .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
409
+ opacity: 0.95;
410
+ }
411
+
412
+ .jp-SideBar
413
+ .lm-TabBar-tab.lm-mod-current
414
+ .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
415
+ opacity: 1;
416
+ }
417
+
418
+ /* Down-area tab bar: the current tab keeps its stock bordered-box
419
+ mechanics (translateY merge with the panel), on hairlines. */
420
+ #jp-down-stack > .lm-TabBar {
421
+ border-top-color: var(--jp-border-color2);
422
+ border-bottom-color: var(--jp-border-color2);
423
+ }
424
+
425
+ #jp-down-stack > .lm-TabBar .lm-TabBar-tab.lm-mod-current {
426
+ border-color: var(--jp-border-color2);
427
+ }
428
+
429
+ /* Stock gives the first-child current tab its own higher-specificity
430
+ border-right rule; recolor it at matching specificity or the seam stays
431
+ on the stronger border-color1 in dark themes. */
432
+ #jp-down-stack > .lm-TabBar .lm-TabBar-tab.lm-mod-current:first-child {
433
+ border-right-color: var(--jp-border-color2);
434
+ }
435
+
436
+ /*
437
+ * Status bar: stock is a layout-color2 band with full-strength text, a
438
+ * hover that jumps to solid layout-color3, and a solid brand-blue block
439
+ * for the popup-open state. Window surface + hairline, muted text that
440
+ * wakes on hover, translucent fills. The hairline is an inset shadow, not
441
+ * a border: the bar is a border-box .lm-Widget and a border would eat into
442
+ * the 24px height its items fill.
443
+ */
444
+ #jp-main-statusbar.jp-StatusBar-Widget {
445
+ background: var(--jp-layout-color1);
446
+ box-shadow: inset 0 1px 0 var(--jp-border-color2);
447
+ }
448
+
449
+ .jp-StatusBar-Widget .jp-StatusBar-Item {
450
+ color: var(--jp-ui-font-color2);
451
+ border-radius: 4px;
452
+ transition:
453
+ background-color 120ms ease,
454
+ color 120ms ease;
455
+ }
456
+
457
+ /* Stock .jp-StatusBar-TextItem hardcodes font-color1; inherit the muted
458
+ item color so hover brightens both together. */
459
+ .jp-StatusBar-Widget .jp-StatusBar-Item .jp-StatusBar-TextItem {
460
+ color: inherit;
461
+ }
462
+
463
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-highlighted:hover {
464
+ color: var(--jp-ui-font-color1);
465
+ background-color: color-mix(
466
+ in srgb,
467
+ var(--jp-ui-font-color1) 8%,
468
+ transparent
469
+ );
470
+ }
471
+
472
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked {
473
+ color: var(--jp-ui-font-color1);
474
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 22%, transparent);
475
+ }
476
+
477
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked:hover {
478
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 30%, transparent);
479
+ }
480
+
481
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked .jp-StatusBar-TextItem {
482
+ color: var(--jp-ui-font-color1);
483
+ }
484
+
485
+ /* The log-console chip marks its open state with jp-mod-selected (a solid
486
+ brand block with white text in stock, no Popup involved). The muting
487
+ rules above would leave grey text on that solid brand background; give
488
+ the state the same translucent-brand treatment as jp-mod-clicked. */
489
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-selected {
490
+ color: var(--jp-ui-font-color1);
491
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 22%, transparent);
492
+ }
493
+
494
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-selected .jp-StatusBar-TextItem {
495
+ color: var(--jp-ui-font-color1);
496
+ }
497
+
498
+ /* Status bar hover popups hardcode a Material shadow; fold them into the
499
+ themed ramp so they soften with everything else. */
500
+ .jp-StatusBar-HoverItem {
501
+ box-shadow: var(--jp-elevation-z6);
502
+ }
503
+
504
+ /*
505
+ * Resize handle affordance: the shell's split handles are 1px wide with an
506
+ * invisible 8px hit area; dock handles between tiled editors are 5px.
507
+ * Stock gives no hover feedback at all. Paint the accent on hover, delayed
508
+ * 150ms so it never flashes while the pointer crosses a boundary (the VS
509
+ * Code sash pattern). Background paint only.
510
+ */
511
+ #jp-main-split-panel > .lm-SplitPanel-handle,
512
+ #jp-main-vsplit-panel > .lm-SplitPanel-handle {
513
+ background-color: transparent;
514
+ transition: background-color 120ms ease;
515
+ }
516
+
517
+ #jp-main-split-panel > .lm-SplitPanel-handle:hover,
518
+ #jp-main-vsplit-panel > .lm-SplitPanel-handle:hover {
519
+ background-color: var(--jp-brand-color1);
520
+ transition-delay: 150ms;
521
+ }
522
+
523
+ /* Dock handles are 5px thick; a solid fill reads fat. Paint a 2px center
524
+ line on the existing ::after hit-area overlay and fade it in. */
525
+ #jp-main-dock-panel .lm-DockPanel-handle::after {
526
+ opacity: 0;
527
+ transition: opacity 120ms ease;
528
+ }
529
+
530
+ #jp-main-dock-panel .lm-DockPanel-handle[data-orientation='horizontal']::after {
531
+ background: linear-gradient(
532
+ to right,
533
+ transparent calc(50% - 1px),
534
+ var(--jp-brand-color1) calc(50% - 1px),
535
+ var(--jp-brand-color1) calc(50% + 1px),
536
+ transparent calc(50% + 1px)
537
+ );
538
+ }
539
+
540
+ #jp-main-dock-panel .lm-DockPanel-handle[data-orientation='vertical']::after {
541
+ background: linear-gradient(
542
+ to bottom,
543
+ transparent calc(50% - 1px),
544
+ var(--jp-brand-color1) calc(50% - 1px),
545
+ var(--jp-brand-color1) calc(50% + 1px),
546
+ transparent calc(50% + 1px)
547
+ );
548
+ }
549
+
550
+ #jp-main-dock-panel .lm-DockPanel-handle:hover::after {
551
+ opacity: 1;
552
+ transition-delay: 150ms;
553
+ }
554
+
555
+ /* -----------------------------------------------------------------------------
556
+ | Document tabs
557
+ |---------------------------------------------------------------------------- */
558
+
559
+ /*
560
+ * Flat modern tab strip: slightly recessed surface, transparent inactive
561
+ * tabs with muted labels, inset hairline separators, and a current tab
562
+ * that merges with the toolbar below plus a rounded accent indicator.
563
+ * Composes with the adaptive tab widths in style/tabs.css (no width/flex/
564
+ * padding here). Doubled classes lift specificity over the stock rules in
565
+ * @jupyterlab/application/style/tabs.css without depending on load order.
566
+ */
567
+
568
+ /* The strip: recessed surface with a hairline baseline drawn as an INSET
569
+ SHADOW (not a border, so the Lumino-measured bar height is unchanged).
570
+ The opaque current tab paints over it, producing the "active tab merges
571
+ with the toolbar below" seam for free. Dock tab bars only: the app's one
572
+ .lm-TabPanel-tabBar is the down-area bar, which draws real top/bottom
573
+ borders of its own — the inset baseline would double its bottom seam. */
574
+ .lm-DockPanel-tabBar[data-orientation='horizontal'] {
575
+ background: var(--jp-layout-color2);
576
+ box-shadow: inset 0 calc(-1 * var(--jp-border-width)) 0
577
+ var(--jp-border-color2);
578
+ }
579
+
580
+ /* Companion recolor for the thin tab-strip scrollbar (style/tabs.css):
581
+ let the strip surface show through instead of a layout-color1 track. */
582
+ .lm-DockPanel-tabBar .lm-TabBar-content::-webkit-scrollbar,
583
+ .lm-DockPanel-tabBar .lm-TabBar-content::-webkit-scrollbar-track {
584
+ background: transparent;
585
+ }
586
+
587
+ /* Inactive tabs: flat on the strip, muted label. border-color transparent
588
+ keeps the stock 1px border in the box model. */
589
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab,
590
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab {
591
+ color: var(--jp-ui-font-color2);
592
+ background: transparent;
593
+ border-color: transparent;
594
+ transition:
595
+ background-color 120ms ease,
596
+ color 120ms ease;
597
+ }
598
+
599
+ /* The stock per-tab bottom hairline is superseded by the strip's inset
600
+ baseline. Single class on purpose: this ties the stock base rule (same
601
+ specificity, we load later) while staying BELOW the stock :focus-visible
602
+ recolor, so the keyboard-focus underline still renders. */
603
+ .lm-DockPanel-tabBar .lm-TabBar-tab:not(.lm-mod-current)::after,
604
+ .lm-DockPanel-tabBar .lm-TabBar-addButton::after {
605
+ border-bottom-color: transparent;
606
+ }
607
+
608
+ /* Hover: a soft half-step toward the active surface. */
609
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab:hover:not(.lm-mod-current),
610
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab:hover:not(.lm-mod-current) {
611
+ color: var(--jp-ui-font-color1);
612
+ background: color-mix(
613
+ in srgb,
614
+ var(--jp-layout-color1) 45%,
615
+ var(--jp-layout-color2)
616
+ );
617
+ }
618
+
619
+ /* Current tab: full-contrast surface + hairline sides. */
620
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab.lm-mod-current,
621
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab.lm-mod-current {
622
+ color: var(--jp-ui-font-color1);
623
+ background: var(--jp-layout-color1);
624
+ border-color: var(--jp-border-color2);
625
+ }
626
+
627
+ /* The stock edge-to-edge 2px brand bar on the app-level active tab is kept
628
+ as-is: it doubles as the tab's separator edge in the flat strip. */
629
+
630
+ /* Inset hairline separators between inactive tabs. Absolutely positioned
631
+ ::before, so no layout impact. Current tabs are excluded because their
632
+ ::before is the accent indicator. */
633
+ .lm-DockPanel-tabBar
634
+ .lm-TabBar-tab
635
+ + .lm-TabBar-tab:not(.lm-mod-current, .jp-mod-current)::before {
636
+ content: '';
637
+ position: absolute;
638
+ top: 6px;
639
+ bottom: 7px;
640
+ left: 0;
641
+ width: var(--jp-border-width);
642
+ background: var(--jp-border-color2);
643
+ }
644
+
645
+ /* No separator immediately right of the current tab — its contrast edge is
646
+ the separator. Must come after the rule above. */
647
+ .lm-DockPanel-tabBar
648
+ .lm-TabBar-tab.lm-mod-current
649
+ + .lm-TabBar-tab.lm-TabBar-tab::before {
650
+ content: none;
651
+ }
652
+
653
+ /* A dragged dock tab is always lm-mod-current (Lumino selects the pressed
654
+ tab on pointerdown, and dock tab bars disallow deselect), so the opaque
655
+ current-tab surface above already keeps its label legible during drags. */
656
+
657
+ /* The + button sits on the strip: drop its own layout-color2 box and give
658
+ it a rounded hover chip consistent with toolbar buttons. */
659
+ .lm-DockPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton,
660
+ .lm-TabPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton {
661
+ background-color: transparent;
662
+ border-radius: 5px;
663
+ transition: background-color 120ms ease;
664
+ }
665
+
666
+ .lm-DockPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton:hover,
667
+ .lm-TabPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton:hover {
668
+ background-color: color-mix(
669
+ in srgb,
670
+ var(--jp-ui-font-color1) 8%,
671
+ transparent
672
+ );
673
+ }
674
+
675
+ /*
676
+ * Tab close button: dimmed until the tab is hovered (45%, not 0, so the
677
+ * target stays discoverable), with a soft rounded chip when the icon
678
+ * itself is hovered. The chip is background + a 2px spread shadow of the
679
+ * same color, so the icon's box never changes and the adaptive tab widths
680
+ * stay stable. Dirty tabs render the unsaved dot inside the close-icon
681
+ * slot and stay at full opacity.
682
+ */
683
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable > .lm-TabBar-tabCloseIcon {
684
+ opacity: 0.45;
685
+ border-radius: 4px;
686
+ transition:
687
+ opacity 100ms ease,
688
+ background-color 100ms ease,
689
+ box-shadow 100ms ease;
690
+ }
691
+
692
+ .lm-DockPanel-tabBar
693
+ .lm-TabBar-tab.lm-mod-closable:hover
694
+ > .lm-TabBar-tabCloseIcon,
695
+ .lm-DockPanel-tabBar
696
+ .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty
697
+ > .lm-TabBar-tabCloseIcon {
698
+ opacity: 1;
699
+ }
700
+
701
+ .lm-DockPanel-tabBar
702
+ .lm-TabBar-tab.lm-mod-closable
703
+ > .lm-TabBar-tabCloseIcon:hover {
704
+ background-color: color-mix(
705
+ in srgb,
706
+ var(--jp-ui-font-color1) 12%,
707
+ transparent
708
+ );
709
+ box-shadow: 0 0 0 2px
710
+ color-mix(in srgb, var(--jp-ui-font-color1) 12%, transparent);
711
+ }
712
+
713
+ /* -----------------------------------------------------------------------------
714
+ | Toolbars
715
+ |---------------------------------------------------------------------------- */
716
+
717
+ /*
718
+ * Toolbar buttons are <jp-button appearance="stealth"> elements; the inner
719
+ * control is an exported shadow part, and document-level ::part() rules win
720
+ * over the component's internal FAST-palette fills — so hover chrome
721
+ * becomes theme-derived and consistent across every toolbar. The blue
722
+ * new-launcher CTA keeps its own accept-color hover (style/base.css).
723
+ */
724
+ .jp-Toolbar .jp-ToolbarButtonComponent::part(control) {
725
+ border-radius: 5px;
726
+ transition: background-color 120ms ease;
727
+ }
728
+
729
+ .jp-Toolbar
730
+ .jp-ToolbarButtonComponent:not(
731
+ [data-command='xtralab:new-launcher']
732
+ ):hover::part(control) {
733
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 8%, transparent);
734
+ }
735
+
736
+ /* Deprecated plain-button path still used by some extensions: same
737
+ treatment, mixed over its opaque resting fill. */
738
+ .jp-Toolbar button.jp-ToolbarButtonComponent {
739
+ border-radius: 5px;
740
+ transition: background-color 120ms ease;
741
+ }
742
+
743
+ .jp-Toolbar button.jp-ToolbarButtonComponent:hover {
744
+ background: color-mix(
745
+ in srgb,
746
+ var(--jp-ui-font-color1) 8%,
747
+ var(--jp-layout-color1)
748
+ );
749
+ }
750
+
751
+ /* -----------------------------------------------------------------------------
752
+ | Controls
753
+ |---------------------------------------------------------------------------- */
754
+
755
+ /* Dialog/action buttons ship letter-spacing 0.8px — a Material convention
756
+ that instantly dates the UI. Near-normal tracking, medium weight, and
757
+ the hover ease stock buttons lack. */
758
+ button.jp-mod-styled {
759
+ letter-spacing: 0.2px;
760
+ font-weight: 500;
761
+ transition:
762
+ background-color 120ms ease,
763
+ color 120ms ease;
764
+ }
765
+
766
+ .jp-Button.jp-mod-minimal,
767
+ button.jp-ToolbarButtonComponent {
768
+ transition: background-color 120ms ease;
769
+ }
770
+
771
+ /* Components that hardcode a radius and would not follow the token: */
772
+
773
+ /* Toolbar dropdowns (kernel switcher, cell type) pin border-radius: 0. */
774
+ .jp-HTMLSelect.jp-DefaultStyle select {
775
+ border-radius: var(--jp-border-radius);
776
+ }
777
+
778
+ /* Flat text buttons (running panel shutdown etc.) hardcode 2px. */
779
+ .jp-Button-flat {
780
+ border-radius: var(--jp-border-radius);
781
+ }
782
+
783
+ /* Stock inputs snap between states instantly. */
784
+ input.jp-mod-styled,
785
+ select.jp-mod-styled,
786
+ .jp-InputGroup input {
787
+ transition:
788
+ border-color 120ms ease,
789
+ box-shadow 120ms ease,
790
+ background-color 120ms ease;
791
+ }
792
+
793
+ /* Stock switches animate at a floaty 0.4s; tighten. */
794
+ .jp-switch-track {
795
+ transition: background-color 150ms ease;
796
+ }
797
+
798
+ .jp-switch-track::before {
799
+ transition: left 150ms ease;
800
+ }
801
+
802
+ /* -----------------------------------------------------------------------------
803
+ | Menus
804
+ |---------------------------------------------------------------------------- */
805
+
806
+ /*
807
+ * Dropdown, context, and submenus: stock is square, hard-bordered
808
+ * (border-color1), with a Material z6 shadow, full-bleed highlights, and a
809
+ * mix-blend-mode separator that goes near-black on dark themes. Every
810
+ * JupyterLab menu carries .jp-ThemedContainer (MenuSvg adds it), giving a
811
+ * deterministic specificity bump over the stock .lm-Menu rules.
812
+ *
813
+ * The 5px side padding insets the item highlight macOS-style. Lumino
814
+ * measures the menu node after attach and before positioning, so the
815
+ * wider box is fully accounted for in its placement math.
816
+ */
817
+ .lm-Menu.jp-ThemedContainer {
818
+ padding: 4px 5px;
819
+ border-radius: 8px;
820
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
821
+ }
822
+
823
+ /* Detach menubar dropdowns: stock pulls them up 2px to fuse with the bar.
824
+ Lumino positions the menu with an inline transform; this CSS `top`
825
+ offsets it. Lumino's max-height math does not know about the offset, so
826
+ a dropdown tall enough to hit the viewport bottom extends 3px past it —
827
+ only its bottom rounding is lost, and only on overfull menus. */
828
+ .lm-Menu.lm-MenuBar-menu.jp-ThemedContainer {
829
+ top: 3px;
830
+ }
831
+
832
+ /* The active-row highlight is painted on the row itself: table-row
833
+ backgrounds paint uniformly across the row, whereas per-cell painting
834
+ breaks — MenuSvg swaps the icon and submenu-caret cells for inline-block
835
+ elements whose boxes do not span the row (the icon cell is 0px tall).
836
+ The menu's 5px side padding keeps the highlight inset from the panel
837
+ edge; rounding is forfeited because border-radius does not render on
838
+ table rows. */
839
+ .lm-Menu.jp-ThemedContainer .lm-Menu-item.lm-mod-active {
840
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 8%, transparent);
841
+ }
842
+
843
+ /* Muted shortcut hints, like every modern menu. */
844
+ .lm-Menu.jp-ThemedContainer .lm-Menu-itemShortcut {
845
+ color: var(--jp-ui-font-color3);
846
+ }
847
+
848
+ /* Stock separators multiply a light grey (mix-blend-mode), which goes
849
+ muddy on dark themes. Plain theme hairline instead. */
850
+ .lm-Menu.jp-ThemedContainer .lm-Menu-item[data-type='separator'] > div::after {
851
+ border-top-color: var(--jp-border-color2);
852
+ mix-blend-mode: normal;
853
+ }
854
+
855
+ /* -----------------------------------------------------------------------------
856
+ | Command palette
857
+ |---------------------------------------------------------------------------- */
858
+
859
+ /* The modal palette as a floating panel. The hairline edge is a shadow
860
+ ring, not a border, so the CSS-positioned panel's size is unchanged. */
861
+ .jp-ModalCommandPalette.jp-ThemedContainer {
862
+ border-radius: 10px;
863
+ overflow: hidden;
864
+ box-shadow:
865
+ 0 0 0 1px color-mix(in srgb, var(--jp-border-color1) 55%, transparent),
866
+ 0 2px 6px var(--jp-shadow-ambient-color),
867
+ 0 16px 48px -12px var(--jp-shadow-umbra-color);
868
+ }
869
+
870
+ /* Rounded search field (keeps stock's inset border + focus treatment). */
871
+ .jp-ModalCommandPalette .lm-CommandPalette-wrapper {
872
+ border-radius: 6px;
873
+ }
874
+
875
+ /* Result rows: stock already insets them 4px in the modal variant.
876
+ (Section headers need no treatment: stock hides them entirely in the
877
+ modal palette.) */
878
+ .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item {
879
+ border-radius: 6px;
880
+ transition: background-color 120ms ease-out;
881
+ }
882
+
883
+ /* -----------------------------------------------------------------------------
884
+ | Dialogs
885
+ |---------------------------------------------------------------------------- */
886
+
887
+ /* Dialog card: top of the radius scale, hairline ring for edge definition
888
+ on dark themes, soft themed elevation. The content node already clips
889
+ children with overflow: hidden. */
890
+ .jp-Dialog.jp-ThemedContainer .jp-Dialog-content {
891
+ border-radius: 12px;
892
+ box-shadow:
893
+ 0 0 0 1px color-mix(in srgb, var(--jp-border-color1) 45%, transparent),
894
+ var(--jp-elevation-z20);
895
+ }
896
+
897
+ /* Smaller + semibold beats big-and-thin (stock is size3 / weight 400). */
898
+ .jp-Dialog.jp-ThemedContainer .jp-Dialog-header {
899
+ font-size: var(--jp-ui-font-size2);
900
+ font-weight: 600;
901
+ }
902
+
903
+ /* Frost the scrim slightly so the dialog pops without a darker tint.
904
+ Progressive enhancement over the theme's --jp-dialog-background. */
905
+ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
906
+ .jp-Dialog.jp-ThemedContainer {
907
+ -webkit-backdrop-filter: blur(3px);
908
+ backdrop-filter: blur(3px);
909
+ }
910
+ }
911
+
912
+ /* -----------------------------------------------------------------------------
913
+ | Completer and tooltip
914
+ |---------------------------------------------------------------------------- */
915
+
916
+ /* Same popover recipe as menus, but NOT frosted: translucency over code
917
+ hurts scan-reading of completions. The completer's JS sizing sets inline
918
+ width/max-height; radius and border-color change nothing it measures,
919
+ and overflow: hidden only clips paint (both children scroll internally). */
920
+ .jp-Completer.jp-ThemedContainer {
921
+ border-radius: 8px;
922
+ overflow: hidden;
923
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
924
+ }
925
+
926
+ .jp-Tooltip.jp-ThemedContainer {
927
+ border-radius: 8px;
928
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
929
+ }
930
+
931
+ /* -----------------------------------------------------------------------------
932
+ | Toast notifications
933
+ |---------------------------------------------------------------------------- */
934
+
935
+ /*
936
+ * Stock marks toast status with a 5px colored top strip. Rounded card with
937
+ * hairline border and a slim colored left accent instead — same five
938
+ * status tokens, modern grammar. Scoped under .jp-ThemedContainer (present
939
+ * on both the corner toast container and the notification-center popup) so
940
+ * these outrank react-toastify's lazy-loaded base CSS by specificity.
941
+ * (.Toastify__toast is react-toastify's own BEM class, hence the
942
+ * selector-class-pattern exemption.)
943
+ */
944
+
945
+ /* stylelint-disable selector-class-pattern */
946
+ .jp-ThemedContainer .Toastify__toast {
947
+ padding: 8px 10px;
948
+ border: var(--jp-border-width) solid var(--jp-border-color2);
949
+ border-radius: 10px;
950
+ box-shadow:
951
+ 0 1px 3px var(--jp-shadow-ambient-color),
952
+ 0 8px 24px -6px var(--jp-shadow-penumbra-color);
953
+ }
954
+
955
+ .jp-ThemedContainer .Toastify__toast.jp-Notification-Toast-error {
956
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
957
+ border-left: 3px solid var(--jp-error-color1);
958
+ }
959
+
960
+ .jp-ThemedContainer .Toastify__toast.jp-Notification-Toast-warning {
961
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
962
+ border-left: 3px solid var(--jp-warn-color1);
963
+ }
964
+
965
+ .jp-ThemedContainer .Toastify__toast.jp-Notification-Toast-info {
966
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
967
+ border-left: 3px solid var(--jp-info-color1);
968
+ }
969
+
970
+ .jp-ThemedContainer .Toastify__toast.jp-Notification-Toast-success {
971
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
972
+ border-left: 3px solid var(--jp-success-color1);
973
+ }
974
+
975
+ .jp-ThemedContainer .Toastify__toast.jp-Notification-Toast-in-progress {
976
+ border-top: var(--jp-border-width) solid var(--jp-border-color2);
977
+ border-left: 3px solid var(--jp-brand-color1);
978
+ }
979
+ /* stylelint-enable selector-class-pattern */
980
+
981
+ /* -----------------------------------------------------------------------------
982
+ | Document search overlay
983
+ |---------------------------------------------------------------------------- */
984
+
985
+ /* The find/replace overlay drops in as a hard-cornered flap with a
986
+ full-strength bordered input. Round its one exposed corner, float it on
987
+ the themed elevation ramp, and give the fields the app-wide soft-border
988
+ + focus-ring treatment. */
989
+ .jp-DocumentSearch-overlay {
990
+ border-bottom-left-radius: 8px;
991
+ border-color: var(--jp-border-color2);
992
+ box-shadow: var(--jp-elevation-z4);
993
+ }
994
+
995
+ .jp-DocumentSearch-input-wrapper {
996
+ border-color: var(--jp-border-color1);
997
+ border-radius: 5px;
998
+ transition:
999
+ border-color 120ms ease,
1000
+ box-shadow 120ms ease;
1001
+ }
1002
+
1003
+ .jp-DocumentSearch-input-wrapper:focus-within {
1004
+ border-color: var(--jp-input-active-border-color, var(--jp-brand-color1));
1005
+ box-shadow: 0 0 0 3px
1006
+ color-mix(
1007
+ in srgb,
1008
+ var(--jp-input-active-border-color, var(--jp-brand-color1)) 22%,
1009
+ transparent
1010
+ );
1011
+ }
1012
+
1013
+ .jp-DocumentSearch-replace-button-wrapper {
1014
+ border-color: var(--jp-border-color1);
1015
+ border-radius: 5px;
1016
+ }
1017
+
1018
+ /* -----------------------------------------------------------------------------
1019
+ | Drag and drop
1020
+ |---------------------------------------------------------------------------- */
1021
+
1022
+ /* Drop-zone overlay: stock hardcodes a Material-blue tint that ignores the
1023
+ active theme, with a dashed marquee border. Soft brand wash, solid
1024
+ hairline, rounded. The overlay is an absolutely positioned
1025
+ pointer-events:none node whose geometry Lumino sets inline. */
1026
+ .lm-DockPanel-overlay {
1027
+ background: color-mix(in srgb, var(--jp-brand-color1) 10%, transparent);
1028
+ border: var(--jp-border-width) solid
1029
+ color-mix(in srgb, var(--jp-brand-color1) 55%, transparent);
1030
+ border-radius: 8px;
1031
+ }
1032
+
1033
+ /* Root-level zones use a 2px border in stock; normalize to the hairline. */
1034
+ .lm-DockPanel-overlay.lm-mod-root-top,
1035
+ .lm-DockPanel-overlay.lm-mod-root-left,
1036
+ .lm-DockPanel-overlay.lm-mod-root-right,
1037
+ .lm-DockPanel-overlay.lm-mod-root-bottom,
1038
+ .lm-DockPanel-overlay.lm-mod-root-center {
1039
+ border-width: var(--jp-border-width);
1040
+ }
1041
+
1042
+ /* Drag ghosts (cursor-following overlay nodes attached to body): one
1043
+ rounded-card language instead of the stock brand top-border on tab
1044
+ ghosts and hardcoded black shadows on cell ghosts. */
1045
+ .lm-TabBar-tab.lm-mod-drag-image.lm-mod-drag-image {
1046
+ border-color: var(--jp-border-color2);
1047
+ border-radius: 6px;
1048
+ box-shadow:
1049
+ 0 8px 24px -6px var(--jp-shadow-umbra-color),
1050
+ 0 2px 8px -2px var(--jp-shadow-penumbra-color);
1051
+ }
1052
+
1053
+ .jp-dragImage {
1054
+ border-radius: 6px;
1055
+ }
1056
+
1057
+ .jp-dragImage-singlePrompt {
1058
+ box-shadow:
1059
+ 0 1px 3px var(--jp-shadow-umbra-color),
1060
+ 0 8px 24px var(--jp-shadow-penumbra-color);
1061
+ }
1062
+
1063
+ .jp-dragImage-multipleBack {
1064
+ border-radius: 6px;
1065
+ box-shadow: 0 1px 3px var(--jp-shadow-umbra-color);
1066
+ }
1067
+
1068
+ /* -----------------------------------------------------------------------------
1069
+ | Notebook cells and content
1070
+ |---------------------------------------------------------------------------- */
1071
+
1072
+ /* Rounded code-cell editor. Stock forces border-radius: 0; the element
1073
+ already has overflow: hidden, so the radius clips the CodeMirror
1074
+ background and active-line highlight cleanly. Console prompt cells share
1075
+ the class. */
1076
+ .jp-InputArea-editor {
1077
+ border-radius: 6px;
1078
+ }
1079
+
1080
+ /* Rendered markdown cells carry a border when active; match. */
1081
+ .jp-MarkdownOutput {
1082
+ border-radius: 6px;
1083
+ }
1084
+
1085
+ /* The Property-Inspector active-cell preview uses the same surface. */
1086
+ .jp-ActiveCellTool .jp-ActiveCellTool-CellContent {
1087
+ border-radius: 6px;
1088
+ }
1089
+
1090
+ /* Command-mode focus ring joins the radius scale. */
1091
+ .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active:focus-visible {
1092
+ border-radius: 6px;
1093
+ }
1094
+
1095
+ /* The 8px active-cell indicator bar becomes a full pill (radius = half the
1096
+ --jp-cell-collapser-width) and animates quietly. Width/flex untouched. */
1097
+ .jp-Collapser {
1098
+ border-radius: 4px;
1099
+ transition:
1100
+ background-color 120ms ease,
1101
+ opacity 120ms ease;
1102
+ }
1103
+
1104
+ /* Calmer collapser hover: translucent brand instead of Material elevation
1105
+ + opacity flicker. */
1106
+ .jp-Notebook .jp-Cell .jp-Collapser:hover {
1107
+ opacity: 1;
1108
+ background: color-mix(in srgb, var(--jp-brand-color1) 55%, transparent);
1109
+ box-shadow: none;
1110
+ }
1111
+
1112
+ .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover {
1113
+ background: var(--jp-brand-color1);
1114
+ }
1115
+
1116
+ /* In[n]/Out[n] two steps smaller with tabular figures (no [9]->[10]
1117
+ jitter). The line box is pinned to the height of one code line so the
1118
+ smaller text stays optically aligned with the first code line; the
1119
+ prompt column width is untouched. Markdown cells keep their own
1120
+ higher-specificity font-size from stock. */
1121
+ .jp-InputPrompt,
1122
+ .jp-OutputPrompt {
1123
+ font-size: calc(var(--jp-code-font-size) - 2px);
1124
+ line-height: calc(var(--jp-code-font-size) * var(--jp-code-line-height));
1125
+ font-variant-numeric: tabular-nums;
1126
+ }
1127
+
1128
+ /* Output-collapse hover overlay: drop the harsh inset inverse hairline,
1129
+ join the radius scale. */
1130
+ .jp-OutputArea-promptOverlay {
1131
+ border-radius: 6px;
1132
+ }
1133
+
1134
+ .jp-OutputArea-promptOverlay:hover {
1135
+ background: var(--jp-layout-color2);
1136
+ box-shadow: none;
1137
+ }
1138
+
1139
+ /* Markdown blockquote: hairline accent instead of the heavy 5px grey slab,
1140
+ quoted text stepped down to the secondary content color. */
1141
+ .jp-RenderedHTMLCommon blockquote {
1142
+ color: var(--jp-content-font-color2);
1143
+ border-left: 3px solid var(--jp-border-color1);
1144
+ }
1145
+
1146
+ /* -----------------------------------------------------------------------------
1147
+ | Terminal
1148
+ |---------------------------------------------------------------------------- */
1149
+
1150
+ /* The terminal widget paints no background of its own, so the 8px body
1151
+ padding shows the dock panel surface as a mismatched frame. Match the
1152
+ xterm theme: 'inherit' reads --jp-layout-color0 in JS, and the forced
1153
+ modes mirror the #fff/#000 the xterm theme hardcodes (they key off the
1154
+ terminal's own theme setting, not the app theme). */
1155
+ .jp-Terminal[data-term-theme='inherit'] {
1156
+ background: var(--jp-layout-color0);
1157
+ }
1158
+
1159
+ .jp-Terminal[data-term-theme='light'] {
1160
+ background: #fff;
1161
+ }
1162
+
1163
+ .jp-Terminal[data-term-theme='dark'] {
1164
+ background: #000;
1165
+ }
1166
+
1167
+ /* -----------------------------------------------------------------------------
1168
+ | Frosted overlays
1169
+ |---------------------------------------------------------------------------- */
1170
+
1171
+ /*
1172
+ * The signature: transient surfaces frost over the workspace, the way
1173
+ * native macOS menus do. Translucent theme-derived background + backdrop
1174
+ * blur, as progressive enhancement — without backdrop-filter support the
1175
+ * stock opaque backgrounds remain. Chromium clips backdrop-filter to
1176
+ * border-radius automatically. Deliberately excludes the completer
1177
+ * (readability over code) and dialogs (content surfaces stay solid).
1178
+ */
1179
+ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
1180
+ /* Context menus + menubar dropdowns. The `background` shorthand also
1181
+ clears the menubar dropdown's scroll-hint gradients, which only appear
1182
+ on menus taller than the viewport — acceptable loss. */
1183
+ .lm-Menu.jp-ThemedContainer,
1184
+ .lm-MenuBar-menu.jp-ThemedContainer {
1185
+ background: color-mix(in srgb, var(--jp-layout-color0) 72%, transparent);
1186
+ -webkit-backdrop-filter: blur(20px) saturate(140%);
1187
+ backdrop-filter: blur(20px) saturate(140%);
1188
+ }
1189
+
1190
+ .jp-ModalCommandPalette.jp-ThemedContainer {
1191
+ background: color-mix(in srgb, var(--jp-layout-color0) 75%, transparent);
1192
+ -webkit-backdrop-filter: blur(24px) saturate(140%);
1193
+ backdrop-filter: blur(24px) saturate(140%);
1194
+ }
1195
+
1196
+ /* Let the frost show through the palette's opaque inner layers (the
1197
+ input field keeps its own --jp-input-active-background). */
1198
+ .jp-ModalCommandPalette .lm-CommandPalette,
1199
+ .jp-ModalCommandPalette .lm-CommandPalette-search,
1200
+ .jp-ModalCommandPalette .lm-CommandPalette-content {
1201
+ background: transparent;
1202
+ }
1203
+
1204
+ .jp-xtralab-Omnibox-panel {
1205
+ background: color-mix(in srgb, var(--jp-layout-color1) 78%, transparent);
1206
+ -webkit-backdrop-filter: blur(24px) saturate(140%);
1207
+ backdrop-filter: blur(24px) saturate(140%);
1208
+ }
1209
+ }
package/style/index.css CHANGED
@@ -1,5 +1,6 @@
1
1
  @import url('base.css');
2
2
  @import url('askAgent.css');
3
+ @import url('chrome.css');
3
4
  @import url('commandBar.css');
4
5
  @import url('editorBreadcrumbs.css');
5
6
  @import url('git.css');
package/style/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import './base.css';
2
2
  import './askAgent.css';
3
+ import './chrome.css';
3
4
  import './commandBar.css';
4
5
  import './editorBreadcrumbs.css';
5
6
  import './git.css';
@@ -349,9 +349,11 @@
349
349
  cursor: not-allowed;
350
350
  }
351
351
 
352
+ /* border-color0: chrome.css remaps color1 onto color2 in light themes, so
353
+ a color1 hover would be identical to the resting color2 border there. */
352
354
  .jp-xtralab-Launcher-agent:hover:not(:disabled) {
353
355
  background-color: var(--jp-layout-color2);
354
- border-color: var(--jp-border-color1);
356
+ border-color: var(--jp-border-color0);
355
357
  }
356
358
 
357
359
  .jp-xtralab-Launcher-agent-icon {
@@ -438,9 +440,10 @@
438
440
  font-size: var(--jp-ui-font-size0);
439
441
  }
440
442
 
443
+ /* border-color0 for the same light-theme reason as the agent cards. */
441
444
  .jp-xtralab-Launcher-mcp-copy:hover {
442
445
  background-color: var(--jp-layout-color2);
443
- border-color: var(--jp-border-color1);
446
+ border-color: var(--jp-border-color0);
444
447
  }
445
448
 
446
449
  .jp-xtralab-Launcher-mcp-copy:focus-visible {
package/style/omnibox.css CHANGED
@@ -30,8 +30,9 @@
30
30
  /* Drop just below the top bar so it reads as a command-center dropdown. */
31
31
  margin-top: calc(var(--jp-private-menubar-height, 28px) + 4px);
32
32
  background: var(--jp-layout-color1);
33
- border: var(--jp-border-width) solid var(--jp-border-color1);
34
- border-radius: 4px;
33
+ border: var(--jp-border-width) solid
34
+ color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
35
+ border-radius: 10px;
35
36
  box-shadow: var(--jp-elevation-z6);
36
37
  }
37
38
 
@@ -50,13 +51,17 @@
50
51
  color: var(--jp-ui-font-color3);
51
52
  }
52
53
 
54
+ /* Side gutters float the active-row highlight inside the panel edge,
55
+ matching the menu/palette treatment; section headers and items shift
56
+ together so their left alignment is preserved. */
53
57
  .jp-xtralab-Omnibox-results {
54
- padding: 4px 0;
58
+ padding: 5px 6px;
55
59
  overflow-y: auto;
56
60
  }
57
61
 
58
62
  .jp-xtralab-Omnibox-sectionHeader {
59
- padding: 6px 14px 2px;
63
+ /* 8px + the results container's 6px gutter = the item rows' 14px inset. */
64
+ padding: 6px 8px 2px;
60
65
  font-size: var(--jp-ui-font-size0);
61
66
  font-weight: 600;
62
67
  color: var(--jp-ui-font-color2);
@@ -68,14 +73,18 @@
68
73
  display: flex;
69
74
  gap: 8px;
70
75
  align-items: center;
71
- padding: 5px 14px;
76
+ padding: 5px 8px;
72
77
  font-size: var(--jp-ui-font-size1);
73
78
  color: var(--jp-ui-font-color1);
74
79
  cursor: pointer;
80
+ border-radius: 6px;
81
+ transition: background-color 120ms ease-out;
75
82
  }
76
83
 
84
+ /* Translucent foreground wash (not an opaque layout color) so the
85
+ highlight reads correctly on the frosted panel background. */
77
86
  .jp-xtralab-Omnibox-item.jp-mod-active {
78
- background: var(--jp-layout-color2);
87
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 8%, transparent);
79
88
  }
80
89
 
81
90
  .jp-xtralab-Omnibox-itemIcon {
@@ -114,7 +123,8 @@
114
123
  }
115
124
 
116
125
  .jp-xtralab-Omnibox-empty {
117
- padding: 14px;
126
+ /* 8px + the results container's 6px gutter = the item rows' 14px inset. */
127
+ padding: 14px 8px;
118
128
  font-size: var(--jp-ui-font-size1);
119
129
  color: var(--jp-ui-font-color2);
120
130
  }
package/style/tabs.css CHANGED
@@ -26,6 +26,15 @@
26
26
  width: auto;
27
27
  }
28
28
 
29
+ /* Breathing room between the label and the close icon. Fit-content tabs put
30
+ the icon flush against the label's last glyph (stock's fixed-width tabs
31
+ hide this with slack space), and the icon-hover chip in chrome.css extends
32
+ 2px beyond the icon box into this gap. */
33
+ .lm-DockPanel-tabBar .lm-TabBar-tab .lm-TabBar-tabCloseIcon,
34
+ .lm-TabPanel-tabBar .lm-TabBar-tab .lm-TabBar-tabCloseIcon {
35
+ margin-left: 4px;
36
+ }
37
+
29
38
  .lm-DockPanel-tabBar .lm-TabBar-content {
30
39
  flex: 0 1 auto;
31
40
  min-width: 0;
@@ -51,9 +51,11 @@
51
51
  cursor: pointer;
52
52
  }
53
53
 
54
+ /* border-color0: chrome.css remaps color1 onto color2 in light themes, so
55
+ a color1 hover would be identical to the resting color2 border there. */
54
56
  .jp-xtralab-Walkthrough-jump:hover {
55
57
  background-color: var(--jp-layout-color2);
56
- border-color: var(--jp-border-color1);
58
+ border-color: var(--jp-border-color0);
57
59
  }
58
60
 
59
61
  .jp-xtralab-Walkthrough-jump:focus-visible {