xtralab 0.12.5 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1167 @@
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
+ /* Carve-out: Lumino's drag cursor backdrop (the invisible scroll box that
210
+ follows the pointer while a splitter handle is held) hides its scrollbars
211
+ with scrollbar-width: none; the universal thin rule above out-specifies
212
+ that and would paint its thumbs as gray pills floating near the cursor. */
213
+ body[data-jp-theme-light] .lm-cursor-backdrop {
214
+ scrollbar-width: none;
215
+ }
216
+
217
+ /* -----------------------------------------------------------------------------
218
+ | Window chrome: seams, menu bar, activity strips, status bar, splitters
219
+ |---------------------------------------------------------------------------- */
220
+
221
+ /* Structural hairlines: recolor the shell's skeleton borders (widths stay). */
222
+ #jp-top-panel {
223
+ border-bottom-color: var(--jp-border-color2);
224
+ }
225
+
226
+ .jp-LabShell[data-shell-mode='single-document'] #jp-menu-panel {
227
+ border-bottom-color: var(--jp-border-color2);
228
+ }
229
+
230
+ .jp-SideArea[data-side='left'] {
231
+ border-right-color: var(--jp-border-color2);
232
+ }
233
+
234
+ .jp-SideArea[data-side='right'] {
235
+ border-left-color: var(--jp-border-color2);
236
+ }
237
+
238
+ /*
239
+ * Re-assert the sidebar width floor over inline styles. Stock intends
240
+ * --jp-sidebar-min-width as the floor for sidebar stack children, but a
241
+ * widget moved into a sidebar (Move Widget To, or a drag) keeps the tiny
242
+ * inline min-width Lumino wrote while it lived in the dock — and inline
243
+ * beats the stylesheet, so the floor never engages for it. Combined with
244
+ * the shell saving the raw split sizes while a sidebar is collapsed
245
+ * (collapsed = ~0, unguarded upstream, unlike the down area's
246
+ * _lastDownAreaSize), a restored workspace then expands that sidebar to a
247
+ * 1px sliver. !important is the one thing that outranks an inline style;
248
+ * with the floor restored, even a zero saved size expands to a usable
249
+ * panel.
250
+ */
251
+ #jp-left-stack > .lm-Widget,
252
+ #jp-right-stack > .lm-Widget {
253
+ min-width: var(--jp-sidebar-min-width) !important;
254
+ }
255
+
256
+ #jp-down-stack {
257
+ border-bottom-color: var(--jp-border-color2);
258
+ }
259
+
260
+ /* Borders framing each open document/panel in the dock. */
261
+ .lm-Widget.lm-DockPanel-widget,
262
+ .lm-TabPanel-stackedPanel.lm-TabPanel-stackedPanel {
263
+ border-color: var(--jp-border-color2);
264
+ }
265
+
266
+ /* The 5px gutters between tiled editors show whatever paints behind the
267
+ dock panel — stock falls through to the body's layout-color3 (#bdbdbd in
268
+ JupyterLab Light). A quiet surface makes split views separate with a
269
+ soft seam instead of a dark bar. */
270
+ #jp-main-dock-panel {
271
+ background: var(--jp-layout-color2);
272
+ }
273
+
274
+ /*
275
+ * Menu bar: stock hover is an opaque grey block, and the OPEN item paints
276
+ * an opaque fill + 1px side borders + z6 shadow to fake a "tab connected
277
+ * to the menu". Rounded translucent highlights instead; the transparent
278
+ * 1px borders Lumino reserves keep their widths, so nothing shifts.
279
+ */
280
+ .lm-MenuBar-item {
281
+ border-radius: 5px;
282
+ transition: background-color 120ms ease;
283
+ }
284
+
285
+ .jp-ThemedContainer .lm-MenuBar-item.lm-mod-active {
286
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 7%, transparent);
287
+ }
288
+
289
+ .jp-ThemedContainer .lm-MenuBar.lm-mod-active .lm-MenuBar-item.lm-mod-active {
290
+ color: var(--jp-ui-font-color0);
291
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 11%, transparent);
292
+ border-left-color: transparent;
293
+ border-right-color: transparent;
294
+ box-shadow: none;
295
+ }
296
+
297
+ .jp-LabShell[data-shell-mode='single-document']
298
+ .lm-MenuBar.lm-mod-active
299
+ .lm-MenuBar-item.lm-mod-active {
300
+ border-top-color: transparent;
301
+ }
302
+
303
+ /*
304
+ * Activity strips (left/right sidebar tab bars, in either orientation) and
305
+ * the down-area tab bar: stock draws them as bordered layout-color2 bands
306
+ * with separators between tabs and an opaque current tab — a classic
307
+ * tab-widget look. Flatten onto the window surface: hairline seams, muted
308
+ * icons that wake on hover, translucent washes, and a 2px brand accent on
309
+ * the current tab's outer edge. All separator overrides change border
310
+ * COLOR only, so the 1px widths Lumino measured stay.
311
+ */
312
+ .jp-SideBar.lm-TabBar,
313
+ #jp-down-stack .lm-TabBar {
314
+ background: var(--jp-layout-color1);
315
+ }
316
+
317
+ /* Hairline between the strip and its neighbor, all four placements. */
318
+ .jp-SideBar.lm-TabBar.jp-mod-left::after {
319
+ border-right-color: var(--jp-border-color2);
320
+ }
321
+
322
+ .jp-SideBar.lm-TabBar.jp-mod-right::after {
323
+ border-left-color: var(--jp-border-color2);
324
+ }
325
+
326
+ .jp-SideBar.lm-TabBar[data-side='top'] {
327
+ border-bottom-color: var(--jp-border-color2);
328
+ }
329
+
330
+ .jp-SideBar.lm-TabBar[data-side='bottom'] {
331
+ border-top-color: var(--jp-border-color2);
332
+ }
333
+
334
+ /* Separators off — vertical orientation… */
335
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
336
+ .lm-TabBar-tab
337
+ + .lm-TabBar-tab,
338
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
339
+ .lm-TabBar-tab.lm-mod-current
340
+ + .lm-TabBar-tab,
341
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
342
+ .lm-TabBar-tab
343
+ + .lm-TabBar-tab.lm-mod-current {
344
+ border-top-color: transparent;
345
+ }
346
+
347
+ .jp-SideBar.lm-TabBar[data-orientation='vertical']
348
+ .lm-TabBar-tab.lm-mod-current:last-child {
349
+ border-bottom-color: transparent;
350
+ }
351
+
352
+ /* …and horizontal orientation. */
353
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
354
+ .lm-TabBar-tab
355
+ + .lm-TabBar-tab,
356
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
357
+ .lm-TabBar-tab.lm-mod-current
358
+ + .lm-TabBar-tab,
359
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
360
+ .lm-TabBar-tab
361
+ + .lm-TabBar-tab.lm-mod-current {
362
+ border-left-color: transparent;
363
+ }
364
+
365
+ .jp-SideBar.lm-TabBar[data-orientation='horizontal']
366
+ .lm-TabBar-tab.lm-mod-current:last-child {
367
+ border-right-color: transparent;
368
+ }
369
+
370
+ /* The current tab's "internal border override" pseudo-element paints an
371
+ opaque frame over the strip's edge hairline; keep the hairline running
372
+ continuously instead. */
373
+ .jp-SideBar .lm-TabBar-tab.lm-mod-current::after {
374
+ border-color: transparent;
375
+ }
376
+
377
+ /* Resting / hover / current fills. */
378
+ .jp-SideBar .lm-TabBar-tab:not(.lm-mod-current),
379
+ #jp-down-stack .lm-TabBar-tab:not(.lm-mod-current) {
380
+ background: transparent;
381
+ transition: background-color 120ms ease;
382
+ }
383
+
384
+ .jp-SideBar .lm-TabBar-tab:hover:not(.lm-mod-current),
385
+ #jp-down-stack .lm-TabBar-tab:hover:not(.lm-mod-current) {
386
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 6%, transparent);
387
+ }
388
+
389
+ .jp-SideBar .lm-TabBar-tab.lm-mod-current {
390
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 4%, transparent);
391
+ }
392
+
393
+ /* Current-tab accent on the strip's outer edge (VS Code activity bar). */
394
+ .jp-SideBar.jp-mod-left .lm-TabBar-tab.lm-mod-current {
395
+ box-shadow: inset 2px 0 0 0 var(--jp-brand-color1);
396
+ }
397
+
398
+ .jp-SideBar.jp-mod-right .lm-TabBar-tab.lm-mod-current {
399
+ box-shadow: inset -2px 0 0 0 var(--jp-brand-color1);
400
+ }
401
+
402
+ .jp-SideBar[data-side='top'] .lm-TabBar-tab.lm-mod-current {
403
+ box-shadow: inset 0 -2px 0 0 var(--jp-brand-color1);
404
+ }
405
+
406
+ .jp-SideBar[data-side='bottom'] .lm-TabBar-tab.lm-mod-current {
407
+ box-shadow: inset 0 2px 0 0 var(--jp-brand-color1);
408
+ }
409
+
410
+ /* Muted icons that wake on hover/selection. */
411
+ .jp-SideBar .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
412
+ opacity: 0.7;
413
+ transition: opacity 120ms ease;
414
+ }
415
+
416
+ .jp-SideBar .lm-TabBar-tab:hover .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
417
+ opacity: 0.95;
418
+ }
419
+
420
+ .jp-SideBar
421
+ .lm-TabBar-tab.lm-mod-current
422
+ .lm-TabBar-tabIcon.jp-SideBar-tabIcon {
423
+ opacity: 1;
424
+ }
425
+
426
+ /* Down-area tab bar: the current tab keeps its stock bordered-box
427
+ mechanics (translateY merge with the panel), on hairlines. */
428
+ #jp-down-stack > .lm-TabBar {
429
+ border-top-color: var(--jp-border-color2);
430
+ border-bottom-color: var(--jp-border-color2);
431
+ }
432
+
433
+ #jp-down-stack > .lm-TabBar .lm-TabBar-tab.lm-mod-current {
434
+ border-color: var(--jp-border-color2);
435
+ }
436
+
437
+ /* Stock gives the first-child current tab its own higher-specificity
438
+ border-right rule; recolor it at matching specificity or the seam stays
439
+ on the stronger border-color1 in dark themes. */
440
+ #jp-down-stack > .lm-TabBar .lm-TabBar-tab.lm-mod-current:first-child {
441
+ border-right-color: var(--jp-border-color2);
442
+ }
443
+
444
+ /*
445
+ * Status bar: stock is a layout-color2 band with full-strength text, a
446
+ * hover that jumps to solid layout-color3, and a solid brand-blue block
447
+ * for the popup-open state. Window surface + hairline, muted text that
448
+ * wakes on hover, translucent fills. The hairline is an inset shadow, not
449
+ * a border: the bar is a border-box .lm-Widget and a border would eat into
450
+ * the 24px height its items fill.
451
+ */
452
+ #jp-main-statusbar.jp-StatusBar-Widget {
453
+ background: var(--jp-layout-color1);
454
+ box-shadow: inset 0 1px 0 var(--jp-border-color2);
455
+ }
456
+
457
+ .jp-StatusBar-Widget .jp-StatusBar-Item {
458
+ color: var(--jp-ui-font-color2);
459
+ border-radius: 4px;
460
+ transition:
461
+ background-color 120ms ease,
462
+ color 120ms ease;
463
+ }
464
+
465
+ /* Stock .jp-StatusBar-TextItem hardcodes font-color1; inherit the muted
466
+ item color so hover brightens both together. */
467
+ .jp-StatusBar-Widget .jp-StatusBar-Item .jp-StatusBar-TextItem {
468
+ color: inherit;
469
+ }
470
+
471
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-highlighted:hover {
472
+ color: var(--jp-ui-font-color1);
473
+ background-color: color-mix(
474
+ in srgb,
475
+ var(--jp-ui-font-color1) 8%,
476
+ transparent
477
+ );
478
+ }
479
+
480
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked {
481
+ color: var(--jp-ui-font-color1);
482
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 22%, transparent);
483
+ }
484
+
485
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked:hover {
486
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 30%, transparent);
487
+ }
488
+
489
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-clicked .jp-StatusBar-TextItem {
490
+ color: var(--jp-ui-font-color1);
491
+ }
492
+
493
+ /* The log-console chip marks its open state with jp-mod-selected (a solid
494
+ brand block with white text in stock, no Popup involved). The muting
495
+ rules above would leave grey text on that solid brand background; give
496
+ the state the same translucent-brand treatment as jp-mod-clicked. */
497
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-selected {
498
+ color: var(--jp-ui-font-color1);
499
+ background-color: color-mix(in srgb, var(--jp-brand-color1) 22%, transparent);
500
+ }
501
+
502
+ .jp-StatusBar-Widget .jp-StatusBar-Item.jp-mod-selected .jp-StatusBar-TextItem {
503
+ color: var(--jp-ui-font-color1);
504
+ }
505
+
506
+ /* Status bar hover popups hardcode a Material shadow; fold them into the
507
+ themed ramp so they soften with everything else. */
508
+ .jp-StatusBar-HoverItem {
509
+ box-shadow: var(--jp-elevation-z6);
510
+ }
511
+
512
+ /*
513
+ * Resize handle affordance: the shell's split handles are 1px wide with an
514
+ * invisible 8px hit area; dock handles between tiled editors are 5px.
515
+ * Stock gives no hover feedback at all. Paint the accent on hover, delayed
516
+ * 150ms so it never flashes while the pointer crosses a boundary (the VS
517
+ * Code sash pattern). Background paint only.
518
+ */
519
+ #jp-main-split-panel > .lm-SplitPanel-handle,
520
+ #jp-main-vsplit-panel > .lm-SplitPanel-handle {
521
+ background-color: transparent;
522
+ transition: background-color 120ms ease;
523
+ }
524
+
525
+ #jp-main-split-panel > .lm-SplitPanel-handle:hover,
526
+ #jp-main-vsplit-panel > .lm-SplitPanel-handle:hover {
527
+ background-color: var(--jp-brand-color1);
528
+ transition-delay: 150ms;
529
+ }
530
+
531
+ /* Dock handles are 5px thick; a solid fill reads fat. Paint a 2px center
532
+ line on the existing ::after hit-area overlay and fade it in. */
533
+ #jp-main-dock-panel .lm-DockPanel-handle::after {
534
+ opacity: 0;
535
+ transition: opacity 120ms ease;
536
+ }
537
+
538
+ #jp-main-dock-panel .lm-DockPanel-handle[data-orientation='horizontal']::after {
539
+ background: linear-gradient(
540
+ to right,
541
+ transparent calc(50% - 1px),
542
+ var(--jp-brand-color1) calc(50% - 1px),
543
+ var(--jp-brand-color1) calc(50% + 1px),
544
+ transparent calc(50% + 1px)
545
+ );
546
+ }
547
+
548
+ #jp-main-dock-panel .lm-DockPanel-handle[data-orientation='vertical']::after {
549
+ background: linear-gradient(
550
+ to bottom,
551
+ transparent calc(50% - 1px),
552
+ var(--jp-brand-color1) calc(50% - 1px),
553
+ var(--jp-brand-color1) calc(50% + 1px),
554
+ transparent calc(50% + 1px)
555
+ );
556
+ }
557
+
558
+ #jp-main-dock-panel .lm-DockPanel-handle:hover::after {
559
+ opacity: 1;
560
+ transition-delay: 150ms;
561
+ }
562
+
563
+ /* -----------------------------------------------------------------------------
564
+ | Document tabs
565
+ |---------------------------------------------------------------------------- */
566
+
567
+ /*
568
+ * Flat modern tab strip: slightly recessed surface, transparent inactive
569
+ * tabs with muted labels, inset hairline separators, and a current tab
570
+ * that merges with the toolbar below plus a rounded accent indicator.
571
+ * Composes with the adaptive tab widths in style/tabs.css (no width/flex/
572
+ * padding here). Doubled classes lift specificity over the stock rules in
573
+ * @jupyterlab/application/style/tabs.css without depending on load order.
574
+ */
575
+
576
+ /* The strip: recessed surface with a hairline baseline drawn as an INSET
577
+ SHADOW (not a border, so the Lumino-measured bar height is unchanged).
578
+ The opaque current tab paints over it, producing the "active tab merges
579
+ with the toolbar below" seam for free. Dock tab bars only: the app's one
580
+ .lm-TabPanel-tabBar is the down-area bar, which draws real top/bottom
581
+ borders of its own — the inset baseline would double its bottom seam. */
582
+ .lm-DockPanel-tabBar[data-orientation='horizontal'] {
583
+ background: var(--jp-layout-color2);
584
+ box-shadow: inset 0 calc(-1 * var(--jp-border-width)) 0
585
+ var(--jp-border-color2);
586
+ }
587
+
588
+ /* Companion recolor for the thin tab-strip scrollbar (style/tabs.css):
589
+ let the strip surface show through instead of a layout-color1 track. */
590
+ .lm-DockPanel-tabBar .lm-TabBar-content::-webkit-scrollbar,
591
+ .lm-DockPanel-tabBar .lm-TabBar-content::-webkit-scrollbar-track {
592
+ background: transparent;
593
+ }
594
+
595
+ /* Inactive tabs: flat on the strip, muted label. border-color transparent
596
+ keeps the stock 1px border in the box model. */
597
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab,
598
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab {
599
+ color: var(--jp-ui-font-color2);
600
+ background: transparent;
601
+ border-color: transparent;
602
+ transition:
603
+ background-color 120ms ease,
604
+ color 120ms ease;
605
+ }
606
+
607
+ /* The stock per-tab bottom hairline is superseded by the strip's inset
608
+ baseline. Single class on purpose: this ties the stock base rule (same
609
+ specificity, we load later) while staying BELOW the stock :focus-visible
610
+ recolor, so the keyboard-focus underline still renders. */
611
+ .lm-DockPanel-tabBar .lm-TabBar-tab:not(.lm-mod-current)::after,
612
+ .lm-DockPanel-tabBar .lm-TabBar-addButton::after {
613
+ border-bottom-color: transparent;
614
+ }
615
+
616
+ /* Hover: a soft half-step toward the active surface. */
617
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab:hover:not(.lm-mod-current),
618
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab:hover:not(.lm-mod-current) {
619
+ color: var(--jp-ui-font-color1);
620
+ background: color-mix(
621
+ in srgb,
622
+ var(--jp-layout-color1) 45%,
623
+ var(--jp-layout-color2)
624
+ );
625
+ }
626
+
627
+ /* Current tab: full-contrast surface + hairline sides. */
628
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab.lm-mod-current,
629
+ .lm-TabPanel-tabBar .lm-TabBar-tab.lm-TabBar-tab.lm-mod-current {
630
+ color: var(--jp-ui-font-color1);
631
+ background: var(--jp-layout-color1);
632
+ border-color: var(--jp-border-color2);
633
+ }
634
+
635
+ /* The stock edge-to-edge 2px brand bar on the app-level active tab is kept
636
+ as-is: it doubles as the tab's separator edge in the flat strip. */
637
+
638
+ /* Inset hairline separators between inactive tabs. Absolutely positioned
639
+ ::before, so no layout impact. Current tabs are excluded because their
640
+ ::before is the accent indicator. */
641
+ .lm-DockPanel-tabBar
642
+ .lm-TabBar-tab
643
+ + .lm-TabBar-tab:not(.lm-mod-current, .jp-mod-current)::before {
644
+ content: '';
645
+ position: absolute;
646
+ top: 6px;
647
+ bottom: 7px;
648
+ left: 0;
649
+ width: var(--jp-border-width);
650
+ background: var(--jp-border-color2);
651
+ }
652
+
653
+ /* No separator immediately right of the current tab — its contrast edge is
654
+ the separator. Must come after the rule above. */
655
+ .lm-DockPanel-tabBar
656
+ .lm-TabBar-tab.lm-mod-current
657
+ + .lm-TabBar-tab.lm-TabBar-tab::before {
658
+ content: none;
659
+ }
660
+
661
+ /* A dragged dock tab is always lm-mod-current (Lumino selects the pressed
662
+ tab on pointerdown, and dock tab bars disallow deselect), so the opaque
663
+ current-tab surface above already keeps its label legible during drags. */
664
+
665
+ /* The + button sits on the strip: drop its own layout-color2 box and give
666
+ it a rounded hover chip consistent with toolbar buttons. */
667
+ .lm-DockPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton,
668
+ .lm-TabPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton {
669
+ background-color: transparent;
670
+ border-radius: 5px;
671
+ transition: background-color 120ms ease;
672
+ }
673
+
674
+ .lm-DockPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton:hover,
675
+ .lm-TabPanel-tabBar .lm-TabBar-addButton.lm-TabBar-addButton:hover {
676
+ background-color: color-mix(
677
+ in srgb,
678
+ var(--jp-ui-font-color1) 8%,
679
+ transparent
680
+ );
681
+ }
682
+
683
+ /*
684
+ * Tab close button: dimmed until the tab is hovered (45%, not 0, so the
685
+ * target stays discoverable), with a soft rounded chip when the icon
686
+ * itself is hovered. The chip is background + a 2px spread shadow of the
687
+ * same color, so the icon's box never changes and the adaptive tab widths
688
+ * stay stable. Dirty tabs render the unsaved dot inside the close-icon
689
+ * slot and stay at full opacity.
690
+ */
691
+ .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable > .lm-TabBar-tabCloseIcon {
692
+ opacity: 0.45;
693
+ border-radius: 4px;
694
+ transition:
695
+ opacity 100ms ease,
696
+ background-color 100ms ease,
697
+ box-shadow 100ms ease;
698
+ }
699
+
700
+ .lm-DockPanel-tabBar
701
+ .lm-TabBar-tab.lm-mod-closable:hover
702
+ > .lm-TabBar-tabCloseIcon,
703
+ .lm-DockPanel-tabBar
704
+ .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty
705
+ > .lm-TabBar-tabCloseIcon {
706
+ opacity: 1;
707
+ }
708
+
709
+ .lm-DockPanel-tabBar
710
+ .lm-TabBar-tab.lm-mod-closable
711
+ > .lm-TabBar-tabCloseIcon:hover {
712
+ background-color: color-mix(
713
+ in srgb,
714
+ var(--jp-ui-font-color1) 12%,
715
+ transparent
716
+ );
717
+ box-shadow: 0 0 0 2px
718
+ color-mix(in srgb, var(--jp-ui-font-color1) 12%, transparent);
719
+ }
720
+
721
+ /* -----------------------------------------------------------------------------
722
+ | Toolbars
723
+ |---------------------------------------------------------------------------- */
724
+
725
+ /*
726
+ * Toolbar buttons are <jp-button appearance="stealth"> elements; the inner
727
+ * control is an exported shadow part, and document-level ::part() rules win
728
+ * over the component's internal FAST-palette fills — so hover chrome
729
+ * becomes theme-derived and consistent across every toolbar. The blue
730
+ * new-launcher CTA keeps its own accept-color hover (style/base.css).
731
+ */
732
+ .jp-Toolbar .jp-ToolbarButtonComponent::part(control) {
733
+ border-radius: 5px;
734
+ transition: background-color 120ms ease;
735
+ }
736
+
737
+ .jp-Toolbar
738
+ .jp-ToolbarButtonComponent:not(
739
+ [data-command='xtralab:new-launcher']
740
+ ):hover::part(control) {
741
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 8%, transparent);
742
+ }
743
+
744
+ /* Deprecated plain-button path still used by some extensions: same
745
+ treatment, mixed over its opaque resting fill. */
746
+ .jp-Toolbar button.jp-ToolbarButtonComponent {
747
+ border-radius: 5px;
748
+ transition: background-color 120ms ease;
749
+ }
750
+
751
+ .jp-Toolbar button.jp-ToolbarButtonComponent:hover {
752
+ background: color-mix(
753
+ in srgb,
754
+ var(--jp-ui-font-color1) 8%,
755
+ var(--jp-layout-color1)
756
+ );
757
+ }
758
+
759
+ /* -----------------------------------------------------------------------------
760
+ | Controls
761
+ |---------------------------------------------------------------------------- */
762
+
763
+ /* Dialog/action buttons ship letter-spacing 0.8px — a Material convention
764
+ that instantly dates the UI. Near-normal tracking, medium weight, and
765
+ the hover ease stock buttons lack. */
766
+ button.jp-mod-styled {
767
+ letter-spacing: 0.2px;
768
+ font-weight: 500;
769
+ transition:
770
+ background-color 120ms ease,
771
+ color 120ms ease;
772
+ }
773
+
774
+ .jp-Button.jp-mod-minimal,
775
+ button.jp-ToolbarButtonComponent {
776
+ transition: background-color 120ms ease;
777
+ }
778
+
779
+ /* Components that hardcode a radius and would not follow the token: */
780
+
781
+ /* Toolbar dropdowns (kernel switcher, cell type) pin border-radius: 0. */
782
+ .jp-HTMLSelect.jp-DefaultStyle select {
783
+ border-radius: var(--jp-border-radius);
784
+ }
785
+
786
+ /* Flat text buttons (running panel shutdown etc.) hardcode 2px. */
787
+ .jp-Button-flat {
788
+ border-radius: var(--jp-border-radius);
789
+ }
790
+
791
+ /* Stock inputs snap between states instantly. */
792
+ input.jp-mod-styled,
793
+ select.jp-mod-styled,
794
+ .jp-InputGroup input {
795
+ transition:
796
+ border-color 120ms ease,
797
+ box-shadow 120ms ease,
798
+ background-color 120ms ease;
799
+ }
800
+
801
+ /* Stock switches animate at a floaty 0.4s; tighten. */
802
+ .jp-switch-track {
803
+ transition: background-color 150ms ease;
804
+ }
805
+
806
+ .jp-switch-track::before {
807
+ transition: left 150ms ease;
808
+ }
809
+
810
+ /* -----------------------------------------------------------------------------
811
+ | Menus
812
+ |---------------------------------------------------------------------------- */
813
+
814
+ /*
815
+ * Dropdown, context, and submenus: stock is square, hard-bordered
816
+ * (border-color1), with a Material z6 shadow, full-bleed highlights, and a
817
+ * mix-blend-mode separator that goes near-black on dark themes. Every
818
+ * JupyterLab menu carries .jp-ThemedContainer (MenuSvg adds it), giving a
819
+ * deterministic specificity bump over the stock .lm-Menu rules.
820
+ *
821
+ * The 5px side padding insets the item highlight macOS-style. Lumino
822
+ * measures the menu node after attach and before positioning, so the
823
+ * wider box is fully accounted for in its placement math.
824
+ */
825
+ .lm-Menu.jp-ThemedContainer {
826
+ padding: 4px 5px;
827
+ border-radius: 8px;
828
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
829
+ }
830
+
831
+ /* Detach menubar dropdowns: stock pulls them up 2px to fuse with the bar.
832
+ Lumino positions the menu with an inline transform; this CSS `top`
833
+ offsets it. Lumino's max-height math does not know about the offset, so
834
+ a dropdown tall enough to hit the viewport bottom extends 3px past it —
835
+ only its bottom rounding is lost, and only on overfull menus. */
836
+ .lm-Menu.lm-MenuBar-menu.jp-ThemedContainer {
837
+ top: 3px;
838
+ }
839
+
840
+ /* The active-row highlight is painted on the row itself: table-row
841
+ backgrounds paint uniformly across the row, whereas per-cell painting
842
+ breaks — MenuSvg swaps the icon and submenu-caret cells for inline-block
843
+ elements whose boxes do not span the row (the icon cell is 0px tall).
844
+ The menu's 5px side padding keeps the highlight inset from the panel
845
+ edge; rounding is forfeited because border-radius does not render on
846
+ table rows. */
847
+ .lm-Menu.jp-ThemedContainer .lm-Menu-item.lm-mod-active {
848
+ background: color-mix(in srgb, var(--jp-ui-font-color1) 8%, transparent);
849
+ }
850
+
851
+ /* Muted shortcut hints, like every modern menu. */
852
+ .lm-Menu.jp-ThemedContainer .lm-Menu-itemShortcut {
853
+ color: var(--jp-ui-font-color3);
854
+ }
855
+
856
+ /* Stock separators multiply a light grey (mix-blend-mode), which goes
857
+ muddy on dark themes. Plain theme hairline instead. */
858
+ .lm-Menu.jp-ThemedContainer .lm-Menu-item[data-type='separator'] > div::after {
859
+ border-top-color: var(--jp-border-color2);
860
+ mix-blend-mode: normal;
861
+ }
862
+
863
+ /* -----------------------------------------------------------------------------
864
+ | Command palette
865
+ |---------------------------------------------------------------------------- */
866
+
867
+ /* The modal palette as a floating panel. The hairline edge is a shadow
868
+ ring, not a border, so the CSS-positioned panel's size is unchanged. */
869
+ .jp-ModalCommandPalette.jp-ThemedContainer {
870
+ border-radius: 10px;
871
+ overflow: hidden;
872
+ box-shadow:
873
+ 0 0 0 1px color-mix(in srgb, var(--jp-border-color1) 55%, transparent),
874
+ 0 2px 6px var(--jp-shadow-ambient-color),
875
+ 0 16px 48px -12px var(--jp-shadow-umbra-color);
876
+ }
877
+
878
+ /* Rounded search field (keeps stock's inset border + focus treatment). */
879
+ .jp-ModalCommandPalette .lm-CommandPalette-wrapper {
880
+ border-radius: 6px;
881
+ }
882
+
883
+ /* Result rows: stock already insets them 4px in the modal variant.
884
+ (Section headers need no treatment: stock hides them entirely in the
885
+ modal palette.) */
886
+ .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item {
887
+ border-radius: 6px;
888
+ transition: background-color 120ms ease-out;
889
+ }
890
+
891
+ /* -----------------------------------------------------------------------------
892
+ | Dialogs
893
+ |---------------------------------------------------------------------------- */
894
+
895
+ /* Dialog card: top of the radius scale, hairline ring for edge definition
896
+ on dark themes, soft themed elevation. The content node already clips
897
+ children with overflow: hidden. */
898
+ .jp-Dialog.jp-ThemedContainer .jp-Dialog-content {
899
+ border-radius: 12px;
900
+ box-shadow:
901
+ 0 0 0 1px color-mix(in srgb, var(--jp-border-color1) 45%, transparent),
902
+ var(--jp-elevation-z20);
903
+ }
904
+
905
+ /* Smaller + semibold beats big-and-thin (stock is size3 / weight 400). */
906
+ .jp-Dialog.jp-ThemedContainer .jp-Dialog-header {
907
+ font-size: var(--jp-ui-font-size2);
908
+ font-weight: 600;
909
+ }
910
+
911
+ /* Frost the scrim slightly so the dialog pops without a darker tint.
912
+ Progressive enhancement over the theme's --jp-dialog-background. */
913
+ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
914
+ .jp-Dialog.jp-ThemedContainer {
915
+ -webkit-backdrop-filter: blur(3px);
916
+ backdrop-filter: blur(3px);
917
+ }
918
+ }
919
+
920
+ /* -----------------------------------------------------------------------------
921
+ | Completer and tooltip
922
+ |---------------------------------------------------------------------------- */
923
+
924
+ /* Same popover recipe as menus, but NOT frosted: translucency over code
925
+ hurts scan-reading of completions. The completer's JS sizing sets inline
926
+ width/max-height; radius and border-color change nothing it measures,
927
+ and overflow: hidden only clips paint (both children scroll internally). */
928
+ .jp-Completer.jp-ThemedContainer {
929
+ border-radius: 8px;
930
+ overflow: hidden;
931
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
932
+ }
933
+
934
+ .jp-Tooltip.jp-ThemedContainer {
935
+ border-radius: 8px;
936
+ border-color: color-mix(in srgb, var(--jp-border-color1) 55%, transparent);
937
+ }
938
+
939
+ /* -----------------------------------------------------------------------------
940
+ | Document search overlay
941
+ |---------------------------------------------------------------------------- */
942
+
943
+ /* The find/replace overlay drops in as a hard-cornered flap with a
944
+ full-strength bordered input. Round its one exposed corner, float it on
945
+ the themed elevation ramp, and give the fields the app-wide soft-border
946
+ + focus-ring treatment. */
947
+ .jp-DocumentSearch-overlay {
948
+ border-bottom-left-radius: 8px;
949
+ border-color: var(--jp-border-color2);
950
+ box-shadow: var(--jp-elevation-z4);
951
+ }
952
+
953
+ .jp-DocumentSearch-input-wrapper {
954
+ border-color: var(--jp-border-color1);
955
+ border-radius: 5px;
956
+ transition:
957
+ border-color 120ms ease,
958
+ box-shadow 120ms ease;
959
+ }
960
+
961
+ .jp-DocumentSearch-input-wrapper:focus-within {
962
+ border-color: var(--jp-input-active-border-color, var(--jp-brand-color1));
963
+ box-shadow: 0 0 0 3px
964
+ color-mix(
965
+ in srgb,
966
+ var(--jp-input-active-border-color, var(--jp-brand-color1)) 22%,
967
+ transparent
968
+ );
969
+ }
970
+
971
+ .jp-DocumentSearch-replace-button-wrapper {
972
+ border-color: var(--jp-border-color1);
973
+ border-radius: 5px;
974
+ }
975
+
976
+ /* -----------------------------------------------------------------------------
977
+ | Drag and drop
978
+ |---------------------------------------------------------------------------- */
979
+
980
+ /* Drop-zone overlay: stock hardcodes a Material-blue tint that ignores the
981
+ active theme, with a dashed marquee border. Soft brand wash, solid
982
+ hairline, rounded. The overlay is an absolutely positioned
983
+ pointer-events:none node whose geometry Lumino sets inline. */
984
+ .lm-DockPanel-overlay {
985
+ background: color-mix(in srgb, var(--jp-brand-color1) 10%, transparent);
986
+ border: var(--jp-border-width) solid
987
+ color-mix(in srgb, var(--jp-brand-color1) 55%, transparent);
988
+ border-radius: 8px;
989
+ }
990
+
991
+ /* Root-level zones use a 2px border in stock; normalize to the hairline. */
992
+ .lm-DockPanel-overlay.lm-mod-root-top,
993
+ .lm-DockPanel-overlay.lm-mod-root-left,
994
+ .lm-DockPanel-overlay.lm-mod-root-right,
995
+ .lm-DockPanel-overlay.lm-mod-root-bottom,
996
+ .lm-DockPanel-overlay.lm-mod-root-center {
997
+ border-width: var(--jp-border-width);
998
+ }
999
+
1000
+ /* Drag ghosts (cursor-following overlay nodes attached to body): one
1001
+ rounded-card language instead of the stock brand top-border on tab
1002
+ ghosts and hardcoded black shadows on cell ghosts. */
1003
+ .lm-TabBar-tab.lm-mod-drag-image.lm-mod-drag-image {
1004
+ border-color: var(--jp-border-color2);
1005
+ border-radius: 6px;
1006
+ box-shadow:
1007
+ 0 8px 24px -6px var(--jp-shadow-umbra-color),
1008
+ 0 2px 8px -2px var(--jp-shadow-penumbra-color);
1009
+ }
1010
+
1011
+ .jp-dragImage {
1012
+ border-radius: 6px;
1013
+ }
1014
+
1015
+ .jp-dragImage-singlePrompt {
1016
+ box-shadow:
1017
+ 0 1px 3px var(--jp-shadow-umbra-color),
1018
+ 0 8px 24px var(--jp-shadow-penumbra-color);
1019
+ }
1020
+
1021
+ .jp-dragImage-multipleBack {
1022
+ border-radius: 6px;
1023
+ box-shadow: 0 1px 3px var(--jp-shadow-umbra-color);
1024
+ }
1025
+
1026
+ /* -----------------------------------------------------------------------------
1027
+ | Notebook cells and content
1028
+ |---------------------------------------------------------------------------- */
1029
+
1030
+ /* Rounded code-cell editor. Stock forces border-radius: 0; the element
1031
+ already has overflow: hidden, so the radius clips the CodeMirror
1032
+ background and active-line highlight cleanly. Console prompt cells share
1033
+ the class. */
1034
+ .jp-InputArea-editor {
1035
+ border-radius: 6px;
1036
+ }
1037
+
1038
+ /* Rendered markdown cells carry a border when active; match. */
1039
+ .jp-MarkdownOutput {
1040
+ border-radius: 6px;
1041
+ }
1042
+
1043
+ /* The Property-Inspector active-cell preview uses the same surface. */
1044
+ .jp-ActiveCellTool .jp-ActiveCellTool-CellContent {
1045
+ border-radius: 6px;
1046
+ }
1047
+
1048
+ /* Command-mode focus ring joins the radius scale. */
1049
+ .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active:focus-visible {
1050
+ border-radius: 6px;
1051
+ }
1052
+
1053
+ /* The 8px active-cell indicator bar becomes a full pill (radius = half the
1054
+ --jp-cell-collapser-width) and animates quietly. Width/flex untouched. */
1055
+ .jp-Collapser {
1056
+ border-radius: 4px;
1057
+ transition:
1058
+ background-color 120ms ease,
1059
+ opacity 120ms ease;
1060
+ }
1061
+
1062
+ /* Calmer collapser hover: translucent brand instead of Material elevation
1063
+ + opacity flicker. */
1064
+ .jp-Notebook .jp-Cell .jp-Collapser:hover {
1065
+ opacity: 1;
1066
+ background: color-mix(in srgb, var(--jp-brand-color1) 55%, transparent);
1067
+ box-shadow: none;
1068
+ }
1069
+
1070
+ .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover {
1071
+ background: var(--jp-brand-color1);
1072
+ }
1073
+
1074
+ /* In[n]/Out[n] two steps smaller with tabular figures (no [9]->[10]
1075
+ jitter). The line box is pinned to the height of one code line so the
1076
+ smaller text stays optically aligned with the first code line; the
1077
+ prompt column width is untouched. Markdown cells keep their own
1078
+ higher-specificity font-size from stock. */
1079
+ .jp-InputPrompt,
1080
+ .jp-OutputPrompt {
1081
+ font-size: calc(var(--jp-code-font-size) - 2px);
1082
+ line-height: calc(var(--jp-code-font-size) * var(--jp-code-line-height));
1083
+ font-variant-numeric: tabular-nums;
1084
+ }
1085
+
1086
+ /* Output-collapse hover overlay: drop the harsh inset inverse hairline,
1087
+ join the radius scale. */
1088
+ .jp-OutputArea-promptOverlay {
1089
+ border-radius: 6px;
1090
+ }
1091
+
1092
+ .jp-OutputArea-promptOverlay:hover {
1093
+ background: var(--jp-layout-color2);
1094
+ box-shadow: none;
1095
+ }
1096
+
1097
+ /* Markdown blockquote: hairline accent instead of the heavy 5px grey slab,
1098
+ quoted text stepped down to the secondary content color. */
1099
+ .jp-RenderedHTMLCommon blockquote {
1100
+ color: var(--jp-content-font-color2);
1101
+ border-left: 3px solid var(--jp-border-color1);
1102
+ }
1103
+
1104
+ /* -----------------------------------------------------------------------------
1105
+ | Terminal
1106
+ |---------------------------------------------------------------------------- */
1107
+
1108
+ /* The terminal widget paints no background of its own, so the 8px body
1109
+ padding shows the dock panel surface as a mismatched frame. Match the
1110
+ xterm theme: 'inherit' reads --jp-layout-color0 in JS, and the forced
1111
+ modes mirror the #fff/#000 the xterm theme hardcodes (they key off the
1112
+ terminal's own theme setting, not the app theme). */
1113
+ .jp-Terminal[data-term-theme='inherit'] {
1114
+ background: var(--jp-layout-color0);
1115
+ }
1116
+
1117
+ .jp-Terminal[data-term-theme='light'] {
1118
+ background: #fff;
1119
+ }
1120
+
1121
+ .jp-Terminal[data-term-theme='dark'] {
1122
+ background: #000;
1123
+ }
1124
+
1125
+ /* -----------------------------------------------------------------------------
1126
+ | Frosted overlays
1127
+ |---------------------------------------------------------------------------- */
1128
+
1129
+ /*
1130
+ * The signature: transient surfaces frost over the workspace, the way
1131
+ * native macOS menus do. Translucent theme-derived background + backdrop
1132
+ * blur, as progressive enhancement — without backdrop-filter support the
1133
+ * stock opaque backgrounds remain. Chromium clips backdrop-filter to
1134
+ * border-radius automatically. Deliberately excludes the completer
1135
+ * (readability over code) and dialogs (content surfaces stay solid).
1136
+ */
1137
+ @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
1138
+ /* Context menus + menubar dropdowns. The `background` shorthand also
1139
+ clears the menubar dropdown's scroll-hint gradients, which only appear
1140
+ on menus taller than the viewport — acceptable loss. */
1141
+ .lm-Menu.jp-ThemedContainer,
1142
+ .lm-MenuBar-menu.jp-ThemedContainer {
1143
+ background: color-mix(in srgb, var(--jp-layout-color0) 72%, transparent);
1144
+ -webkit-backdrop-filter: blur(20px) saturate(140%);
1145
+ backdrop-filter: blur(20px) saturate(140%);
1146
+ }
1147
+
1148
+ .jp-ModalCommandPalette.jp-ThemedContainer {
1149
+ background: color-mix(in srgb, var(--jp-layout-color0) 75%, transparent);
1150
+ -webkit-backdrop-filter: blur(24px) saturate(140%);
1151
+ backdrop-filter: blur(24px) saturate(140%);
1152
+ }
1153
+
1154
+ /* Let the frost show through the palette's opaque inner layers (the
1155
+ input field keeps its own --jp-input-active-background). */
1156
+ .jp-ModalCommandPalette .lm-CommandPalette,
1157
+ .jp-ModalCommandPalette .lm-CommandPalette-search,
1158
+ .jp-ModalCommandPalette .lm-CommandPalette-content {
1159
+ background: transparent;
1160
+ }
1161
+
1162
+ .jp-xtralab-Omnibox-panel {
1163
+ background: color-mix(in srgb, var(--jp-layout-color1) 78%, transparent);
1164
+ -webkit-backdrop-filter: blur(24px) saturate(140%);
1165
+ backdrop-filter: blur(24px) saturate(140%);
1166
+ }
1167
+ }