@gallerist/theme-default 0.4.0 → 0.5.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/README.md CHANGED
@@ -41,10 +41,47 @@ screen; an inline viewer keeps it. Keep them with `--gallerist-phone-zoom: flex`
41
41
  shows − and + only). A bar whose only tools are these two (and `controls: false`) still shows on a
42
42
  phone, empty: leave the plugins out there, or keep the tools with the tokens.
43
43
 
44
+ The bar's tools are `--gallerist-tool-size` (44px) with `--gallerist-tool-icon` glyphs (22px;
45
+ Close's `--gallerist-close-icon`, the tool glyph unless set). With a fine pointer (a mouse or trackpad)
46
+ the Console skin's bar is compact: 36px tools, 18px glyphs, Close's 2px larger (Console sets
47
+ `--gallerist-close-icon` to `--gallerist-tool-icon` + 2px, so it follows a page's glyph size; set it
48
+ too to size Close apart), and plugin-zoom's "− 100% +" one bordered group 30px tall
49
+ (`--gallerist-zoom-group: 1`; 0, the default, keeps three loose tools; a unitless 0 or 1, nothing
50
+ else). A touch keeps 44px targets; Gallery and Editorial keep 44px tools. `--gallerist-close-rule` is
51
+ the room before Close (a length: Console 9px; 0px, the default, none), not the line: the 1 × 20 hairline in it is
52
+ drawn as a border, so forced colours keep it.
53
+
54
+ The rail (`.gallerist-thumbs`) has a `scroll-padding` of `--gallerist-rail-fade` (40px) at its ends,
55
+ inline on a sideways rail and block on a side rail: plugin-thumbnails reads it to keep the current
56
+ card clear of the end fades and the ‹ › buttons in them, and a card focused with Tab lands clear too.
57
+ On a phone (600px wide or less with a coarse pointer, where the ‹ › buttons never show) the fade is
58
+ 16px (0.5), so the current card kept clear of it leaves room for the next card whole beside it. A
59
+ page's own `--gallerist-rail-fade` wins (the theme's tokens are in a cascade layer).
60
+
61
+ Loading (0.5): an item's `placeholder` image is blurred `--gallerist-placeholder-blur` (6px) and
62
+ clipped to the image's box; the image fades in over it in `--gallerist-dur-reveal` (150ms). A box
63
+ with no size to go by takes `--gallerist-media-ratio` (`3 / 2`). A load still running after
64
+ `--gallerist-loading-delay` (400ms) shows a "Loading full size" pill (the panel, hairline and muted
65
+ text tokens; no warning colours). With no placeholder the box is a skeleton after 300ms:
66
+ `--gallerist-placeholder` with a `--gallerist-shimmer` sweep, gone at once when the image is in. No
67
+ loading animation outlives the load. See the renderer's README.
68
+
69
+ The rail's current label (a flat rail's group label, a timeline's time label) is
70
+ `--gallerist-label-current` (the accent) at `--gallerist-label-current-weight` (500). A focused thumb's
71
+ ring is 2px `--gallerist-focus` in `--gallerist-thumb-focus-style` (`solid`; `dashed` tells it apart
72
+ from a solid selection ring), 2px out, or `--gallerist-thumb-focus-offset-current` (2px) out on the
73
+ current thumb, whose ring (`--gallerist-thumb-ring`, `--gallerist-item-ring`) may sit outside it. A
74
+ focused thumb that isn't current shows at `--gallerist-thumb-focus-opacity` (1, as when hovered);
75
+ `var(--gallerist-thumb-idle-opacity)` keeps it dimmed, so only the current one is bright (hover still
76
+ brightens it).
77
+
44
78
  The theme follows `forced-colors: active` (Windows High Contrast): the View popover's chosen segment
45
79
  takes the system's selection colours and the focus rings the text colour. The rail's
46
80
  item clusters (`thumbnails({ cluster })`) use `--gallerist-cluster-inner` (2px) inside a cluster and
47
- `--gallerist-cluster-gap` (8px) between two.
81
+ `--gallerist-cluster-gap` (8px) between two. An item thumb's badge (`thumbnails({ renderItemBadge })`)
82
+ sits `--gallerist-thumb-badge-inset-block` from its image's top and bottom, as `inset-block` takes
83
+ them: `3px auto`, the top end corner; `auto 3px` puts it in the bottom end corner, still on the image
84
+ (a caption band under it stays clear).
48
85
 
49
86
  Full docs: the [monorepo README](https://github.com/shafayet9780/gallerist#readme) and [`docs/`](https://github.com/shafayet9780/gallerist/tree/main/docs).
50
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gallerist/theme-default",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Default Gallerist theme — pure CSS, no JS dependency. Driven by --gallerist-* custom properties.",
5
5
  "license": "MIT",
6
6
  "sideEffects": [
package/src/base.css CHANGED
@@ -15,6 +15,16 @@
15
15
  .gallerist {
16
16
  /* structure: sizes every skin shares (a skin may tune them; the layout lint checks each skin) */
17
17
  --gallerist-target: 44px;
18
+ /* the bar's tools: their box and glyph (Close's glyph its own); Console takes 36 / 18 / 20 with
19
+ a fine pointer. A touch keeps the 44px target. */
20
+ --gallerist-tool-size: var(--gallerist-target);
21
+ --gallerist-tool-icon: 22px;
22
+ --gallerist-close-icon: var(--gallerist-tool-icon);
23
+ /* plugin-zoom's − 100% +: 0 three loose tools, 1 one bordered group a tool's height less 6px
24
+ (Console with a fine pointer) */
25
+ --gallerist-zoom-group: 0;
26
+ /* room before Close, a hairline 20px tall at its start (Console 9px; 0: none) */
27
+ --gallerist-close-rule: 0px;
18
28
  --gallerist-thumb-h: 84px;
19
29
  --gallerist-rail-handle-h: 22px;
20
30
  --gallerist-toolbar-h: 56px; /* toolbar band height; a vertical rail starts below it */
@@ -33,6 +43,13 @@
33
43
  --gallerist-dur-gentle: 280ms;
34
44
  --gallerist-dur-exit: 180ms; /* exits run shorter than entrances */
35
45
  --gallerist-dur-panel: 220ms; /* the rail collapsing, the item column opening (plugin-thumbnails) */
46
+ --gallerist-dur-reveal: 150ms; /* a loaded image fading in over its placeholder */
47
+
48
+ /* loading: an image placeholder's blur, the ratio of a box with no size to go by (a skeleton),
49
+ and how long a load runs before its "Loading full size" pill shows */
50
+ --gallerist-placeholder-blur: 6px;
51
+ --gallerist-media-ratio: 3 / 2;
52
+ --gallerist-loading-delay: 400ms;
36
53
 
37
54
  /* the accent: each skin names its accents as a dark/light pair, the scheme picks one */
38
55
  --gallerist-accent: var(--gallerist-accent-dark);
@@ -87,6 +104,16 @@
87
104
  /* item clusters (thumbnails `cluster`): the gap inside one, and between two */
88
105
  --gallerist-cluster-inner: 2px;
89
106
  --gallerist-cluster-gap: 8px;
107
+ /* an item thumb's badge (thumbnails `renderItemBadge`), its `inset-block` from the image's edges:
108
+ the top end corner; `auto 3px` takes it to the bottom end */
109
+ --gallerist-thumb-badge-inset-block: 3px auto;
110
+ /* the rail's current group label (flat) or time label (timeline), and a focused thumb's ring:
111
+ its outline-style, and its offset on the current thumb (whose ring is outside it). A focused
112
+ thumb that isn't current: --gallerist-thumb-focus-opacity (unset: 1) */
113
+ --gallerist-label-current: var(--gallerist-accent);
114
+ --gallerist-label-current-weight: 500;
115
+ --gallerist-thumb-focus-style: solid;
116
+ --gallerist-thumb-focus-offset-current: 2px;
90
117
 
91
118
  /* popovers (the View menu, the shortcut list) sit a step above the bands; a segmented control
92
119
  is a recessed track with its checked segment raised */
@@ -100,6 +127,13 @@
100
127
  --gallerist-arrow-hover-bg: var(--gallerist-arrow-bg);
101
128
  --gallerist-itemnav-button-hover-bg: var(--gallerist-itemnav-button-bg);
102
129
  }
130
+ /* a phone's rail fades 16px (no ‹ › page buttons sit in it on touch): the current card kept clear
131
+ of the fade leaves room for the card ahead whole beside it */
132
+ @media (max-width: 600px) and (pointer: coarse) {
133
+ .gallerist {
134
+ --gallerist-rail-fade: 16px;
135
+ }
136
+ }
103
137
  }
104
138
 
105
139
  .gallerist {
@@ -297,14 +331,143 @@
297
331
  width: 100%;
298
332
  height: 100%;
299
333
  object-fit: contain;
300
- background-repeat: no-repeat;
301
- background-position: center;
302
334
  opacity: 0;
303
- transition: opacity 180ms ease-out;
335
+ transition: opacity var(--gallerist-dur-reveal) var(--gallerist-ease-out);
304
336
  }
305
337
  .gallerist-media-image[data-gallerist-loaded] {
306
338
  opacity: 1;
307
339
  }
340
+ .gallerist-media-image[data-gallerist-error] {
341
+ visibility: hidden;
342
+ }
343
+ /* `item.placeholder` in the image's box (ratio: naturalSize, the placeholder's, or the token). An
344
+ image one is blurred, overscanned 2× the blur and clipped (no fringe), sharp as the image fades in,
345
+ then hidden; a failure keeps it, sharp. None: a skeleton after 300ms, gone when the image is in. */
346
+ .gallerist-content {
347
+ container-type: size;
348
+ }
349
+ .gallerist-media-placeholder {
350
+ --_i: 0px;
351
+ position: absolute;
352
+ inset: 0;
353
+ margin: auto;
354
+ width: min(100cqw - 2 * var(--_i), (100cqh - 2 * var(--_i)) * var(--gallerist-media-ratio));
355
+ height: min(100cqh - 2 * var(--_i), (100cqw - 2 * var(--_i)) / (var(--gallerist-media-ratio)));
356
+ overflow: hidden;
357
+ }
358
+ .gallerist[data-gallerist-frame] .gallerist-media-placeholder {
359
+ --_i: var(--gallerist-frame-inset);
360
+ }
361
+ .gallerist-media-placeholder > img {
362
+ --_o: calc(-2 * var(--gallerist-placeholder-blur));
363
+ position: absolute;
364
+ inset: var(--_o);
365
+ width: calc(100% - 2 * var(--_o));
366
+ height: calc(100% - 2 * var(--_o));
367
+ object-fit: cover;
368
+ filter: blur(var(--gallerist-placeholder-blur));
369
+ transition: var(--gallerist-dur-reveal) var(--gallerist-ease-out);
370
+ transition-property: filter, inset, width, height;
371
+ }
372
+ .gallerist-media-placeholder:is([data-gallerist-loaded], [data-gallerist-error]) > img {
373
+ --_o: 0px;
374
+ filter: none;
375
+ }
376
+ .gallerist-media-placeholder[data-gallerist-loaded] {
377
+ visibility: hidden;
378
+ transition: visibility 0s var(--gallerist-dur-reveal);
379
+ }
380
+ [data-gallerist-skeleton]:not([data-gallerist-loaded]) {
381
+ background: var(--gallerist-placeholder);
382
+ animation: gallerist-fade var(--gallerist-dur-exit) 0.3s backwards;
383
+ }
384
+ [data-gallerist-skeleton]:not([data-gallerist-loaded])::after {
385
+ content: "";
386
+ position: absolute;
387
+ inset: 0;
388
+ background: linear-gradient(
389
+ 100deg,
390
+ transparent 30%,
391
+ var(--gallerist-shimmer) 50%,
392
+ transparent 70%
393
+ )
394
+ 150% 0 / 220% 100%;
395
+ animation: gallerist-shimmer 1.4s ease-in-out 0.3s infinite;
396
+ }
397
+ @keyframes gallerist-shimmer {
398
+ to {
399
+ background-position: -50% 0;
400
+ }
401
+ }
402
+ /* a slow load's pill, bottom end: after the delay, or at once on a failure (Retry). Neutral */
403
+ .gallerist-media-pill {
404
+ position: absolute;
405
+ bottom: 12px;
406
+ inset-inline-end: 12px;
407
+ display: flex;
408
+ align-items: center;
409
+ gap: 8px;
410
+ max-width: calc(100% - 24px);
411
+ min-height: 30px;
412
+ box-sizing: border-box;
413
+ padding: 2px 12px 2px 10px;
414
+ border: 1px solid var(--gallerist-hairline);
415
+ border-radius: 99px;
416
+ background: var(--gallerist-panel);
417
+ color: var(--gallerist-fg-muted);
418
+ font: 12.5px / 1.3 var(--gallerist-font);
419
+ animation: gallerist-fade var(--gallerist-dur-exit) var(--gallerist-loading-delay) backwards;
420
+ }
421
+ /* the spinner; on a failure, a ! in a ring */
422
+ .gallerist-media-pill::before {
423
+ content: "";
424
+ flex: none;
425
+ box-sizing: border-box;
426
+ width: 13px;
427
+ height: 13px;
428
+ border: 1.5px solid;
429
+ border-inline-end-color: transparent;
430
+ border-radius: 50%;
431
+ font: 700 9px / 10px var(--gallerist-font);
432
+ text-align: center;
433
+ animation: gallerist-spin 0.9s linear infinite;
434
+ }
435
+ [data-gallerist-error] > .gallerist-media-pill {
436
+ color: var(--gallerist-fg);
437
+ animation: none;
438
+ }
439
+ [data-gallerist-error] > .gallerist-media-pill::before {
440
+ content: "!";
441
+ border-color: currentColor;
442
+ animation: none;
443
+ }
444
+ .gallerist-media-pill > button {
445
+ font: inherit;
446
+ font-weight: 600;
447
+ color: inherit;
448
+ background: none;
449
+ border: 0;
450
+ padding: 3px 2px;
451
+ border-radius: 4px;
452
+ text-decoration: underline;
453
+ text-underline-offset: 3px;
454
+ cursor: pointer;
455
+ }
456
+ .gallerist-media-pill > button::before {
457
+ content: "·" / "";
458
+ display: inline-block;
459
+ margin-inline-end: 8px;
460
+ color: var(--gallerist-fg-muted);
461
+ }
462
+ .gallerist-media-pill > button:focus-visible {
463
+ outline: 2px solid var(--gallerist-focus);
464
+ outline-offset: 2px;
465
+ }
466
+ @keyframes gallerist-spin {
467
+ to {
468
+ transform: rotate(1turn);
469
+ }
470
+ }
308
471
  /* A failed load shows a centered error card (icon + the item's alt as a caption) instead of a
309
472
  blank stage or the browser's default top-left broken-image glyph (I-UX3). The broken <img>
310
473
  itself stays hidden (opacity:0); the adapter injects .gallerist-media-error as a sibling. */
@@ -330,34 +493,14 @@
330
493
  max-width: 40ch;
331
494
  color: var(--gallerist-fg);
332
495
  }
333
- /* Loading shimmer for slow media — shown only while an image is still pending (no loaded/error
334
- marker yet), delayed so fast loads never flash it. Degrades to nothing where :has is absent. */
335
- .gallerist-content:has(
336
- .gallerist-media-image:not([data-gallerist-loaded]):not([data-gallerist-error])
337
- )::before {
338
- content: "";
339
- position: absolute;
340
- inset: 0;
341
- pointer-events: none;
342
- background: linear-gradient(
343
- 100deg,
344
- transparent 35%,
345
- var(--gallerist-shimmer) 50%,
346
- transparent 65%
347
- );
348
- background-size: 200% 100%;
349
- animation: gallerist-shimmer 1.4s ease-in-out 0.6s infinite;
350
- }
351
- @keyframes gallerist-shimmer {
352
- from {
353
- background-position: 150% 0;
354
- }
355
- to {
356
- background-position: -50% 0;
357
- }
358
- }
359
496
  @media (prefers-reduced-motion: reduce) {
360
- .gallerist-content::before {
497
+ .gallerist-media-placeholder > img {
498
+ --_o: 0px;
499
+ filter: none;
500
+ transition: none;
501
+ }
502
+ [data-gallerist-skeleton]:not([data-gallerist-loaded])::after,
503
+ .gallerist-media-pill::before {
361
504
  animation: none;
362
505
  }
363
506
  }
@@ -497,6 +640,9 @@
497
640
  align-items: center;
498
641
  padding: 8px 12px;
499
642
  overflow-x: auto;
643
+ /* a card brought into view (the current one, a focused one) lands clear of the end fades, and of
644
+ the ‹ › page buttons in them (plugin-thumbnails reads it) */
645
+ scroll-padding-inline: var(--gallerist-rail-fade);
500
646
  scrollbar-width: none;
501
647
  -webkit-user-select: none;
502
648
  user-select: none;
@@ -509,6 +655,7 @@
509
655
  }
510
656
  .gallerist-thumbs[data-gallerist-scroll="y"] {
511
657
  --_fade-to: to bottom;
658
+ scroll-padding: var(--gallerist-rail-fade) 0;
512
659
  }
513
660
  .gallerist[data-gallerist-dir="rtl"] .gallerist-thumbs[data-gallerist-scroll="x"] {
514
661
  --_fade-to: to left;
@@ -606,21 +753,27 @@
606
753
  border-color: var(--gallerist-thumb-active-border);
607
754
  box-shadow: var(--gallerist-thumb-ring);
608
755
  }
609
- .gallerist-thumb:not([data-active]) > .gallerist-thumb-img,
610
- .gallerist-thumb-item:not([data-active]) > .gallerist-thumb-img {
756
+ :is(.gallerist-thumb, .gallerist-thumb-item):not([data-active]) > .gallerist-thumb-img {
611
757
  opacity: var(--gallerist-thumb-idle-opacity);
612
758
  transition: opacity var(--gallerist-dur-gentle) var(--gallerist-ease-out);
613
759
  }
614
- .gallerist-thumb:is(:hover, :focus-visible) > .gallerist-thumb-img,
615
- .gallerist-thumb-item:is(:hover, :focus-visible) > .gallerist-thumb-img {
760
+ :is(.gallerist-thumb, .gallerist-thumb-item):not([data-active]):focus-visible
761
+ > .gallerist-thumb-img {
762
+ opacity: var(--gallerist-thumb-focus-opacity, 1);
763
+ }
764
+ :is(.gallerist-thumb, .gallerist-thumb-item):not([data-active]):hover > .gallerist-thumb-img {
616
765
  opacity: 1;
617
766
  }
618
767
  .gallerist-thumb:focus-visible,
619
768
  .gallerist-thumb-item:focus-visible,
620
769
  .gallerist-grid-cell:focus-visible {
621
- outline: 2px solid var(--gallerist-focus);
770
+ outline: 2px var(--gallerist-thumb-focus-style) var(--gallerist-focus);
622
771
  outline-offset: 2px;
623
772
  }
773
+ /* the current thumb's ring is outside it: focus there may sit further out */
774
+ :is(.gallerist-thumb, .gallerist-thumb-item)[data-active]:focus-visible {
775
+ outline-offset: var(--gallerist-thumb-focus-offset-current);
776
+ }
624
777
  .gallerist-thumb-img {
625
778
  width: 100%;
626
779
  object-fit: cover;
@@ -707,10 +860,13 @@
707
860
  .gallerist-thumbs-aside[hidden] {
708
861
  display: none;
709
862
  }
863
+ /* a grid, not a flex column: its image's row is a box the badge can sit in (a caption band or a
864
+ touch's 44px under the image stay out of it) */
710
865
  .gallerist-thumb-item {
711
866
  position: relative;
712
- display: flex;
713
- flex-direction: column;
867
+ display: grid;
868
+ grid-template-columns: minmax(0, 1fr);
869
+ align-content: start;
714
870
  flex: 0 0 auto;
715
871
  width: calc(var(--gallerist-thumb-h) * 1.2);
716
872
  padding: 0;
@@ -810,10 +966,11 @@
810
966
  isolation: isolate; /* keeps the track line behind its own label */
811
967
  }
812
968
  .gallerist-thumb-wrap[data-active] .gallerist-thumb-time {
813
- color: var(--gallerist-accent);
969
+ color: var(--gallerist-label-current);
970
+ font-weight: var(--gallerist-label-current-weight);
814
971
  }
815
972
  .gallerist-thumb-wrap[data-active] .gallerist-thumb-time::before {
816
- background: var(--gallerist-accent);
973
+ background: var(--gallerist-label-current);
817
974
  }
818
975
  /* numbered items (thumbnails `numberItems`) */
819
976
  .gallerist-thumb-num {
@@ -932,7 +1089,8 @@
932
1089
  font-family: var(--gallerist-mono);
933
1090
  }
934
1091
  .gallerist-thumb-group[data-active] .gallerist-thumb-group-cap {
935
- color: var(--gallerist-accent);
1092
+ color: var(--gallerist-label-current);
1093
+ font-weight: var(--gallerist-label-current-weight);
936
1094
  }
937
1095
  .gallerist-thumb-group-row {
938
1096
  display: flex;
@@ -981,7 +1139,7 @@
981
1139
  .gallerist-thumb-group-head {
982
1140
  display: flex;
983
1141
  align-items: center;
984
- gap: 8px;
1142
+ gap: 12px; /* the label, then the meta (the mockup) */
985
1143
  min-height: 14px;
986
1144
  }
987
1145
  .gallerist-thumb-group-head[hidden] {
@@ -996,10 +1154,13 @@
996
1154
  width: calc(var(--gallerist-thumb-h) * 1.4);
997
1155
  min-height: 14px;
998
1156
  }
999
- /* an item's badge: the top end corner (a number from `numberItems` has the start) */
1157
+ /* an item's badge: the image's top end corner (a number from `numberItems` has the start), or its
1158
+ bottom end with `--gallerist-thumb-badge-inset-block: auto 3px`; placed in the image's grid row (an
1159
+ absolute box's `auto` grid line is the thumb's edge: the row's end line is named) */
1000
1160
  .gallerist-thumb-badge {
1001
1161
  position: absolute;
1002
- top: 3px;
1162
+ grid-row: 1 / 2;
1163
+ inset-block: var(--gallerist-thumb-badge-inset-block);
1003
1164
  inset-inline-end: 3px;
1004
1165
  display: flex;
1005
1166
  align-items: center;
@@ -1119,6 +1280,8 @@
1119
1280
  backdrop-filter: var(--gallerist-blur);
1120
1281
  }
1121
1282
  .gallerist-bar button {
1283
+ min-width: var(--gallerist-tool-size);
1284
+ min-height: var(--gallerist-tool-size);
1122
1285
  border: var(--gallerist-tool-border);
1123
1286
  background: var(--gallerist-tool-bg);
1124
1287
  color: var(--gallerist-tool-fg);
@@ -1171,21 +1334,77 @@
1171
1334
  display: block;
1172
1335
  pointer-events: none;
1173
1336
  }
1337
+ .gallerist-bar .gallerist-icon {
1338
+ width: var(--gallerist-tool-icon);
1339
+ height: var(--gallerist-tool-icon);
1340
+ }
1341
+ .gallerist-bar .gallerist-close .gallerist-icon {
1342
+ width: var(--gallerist-close-icon);
1343
+ height: var(--gallerist-close-icon);
1344
+ }
1345
+ /* a hairline before Close, in the room --gallerist-close-rule makes (none at 0) */
1346
+ .gallerist-bar .gallerist-close {
1347
+ position: relative;
1348
+ margin-inline-start: var(--gallerist-close-rule);
1349
+ }
1350
+ .gallerist-bar .gallerist-close::before {
1351
+ content: "";
1352
+ position: absolute;
1353
+ inset-inline-start: calc(-1 * var(--gallerist-close-rule));
1354
+ top: calc(50% - 10px);
1355
+ height: 20px;
1356
+ /* a border, not a background: forced colours keep a border's line (in the text colour) */
1357
+ border-inline-start: min(1px, var(--gallerist-close-rule)) solid var(--gallerist-hairline);
1358
+ pointer-events: none;
1359
+ }
1174
1360
 
1175
1361
  /* ── the zoom tool (plugin-zoom): − 100% + ───────────────────────────────────────── */
1362
+ /* --gallerist-zoom-group (--_g) 0: three tools 2px apart; 1: one group in a hairline, its parts
1363
+ 6px narrower and 8px shorter than a tool (30 × 28 of 36), the percentage between two hairlines */
1176
1364
  .gallerist-zoom-tool {
1365
+ --_g: var(--gallerist-zoom-group);
1177
1366
  display: flex;
1178
1367
  align-items: center;
1179
- gap: 2px;
1368
+ gap: calc(2px - 2px * var(--_g));
1369
+ border: calc(1px * var(--_g)) solid var(--gallerist-hairline);
1370
+ border-radius: var(--gallerist-radius);
1180
1371
  }
1181
1372
  .gallerist-zoom-tool[hidden] {
1182
1373
  display: none;
1183
1374
  }
1375
+ /* (a bar tool's specificity, so the percentage's own width wins) */
1376
+ .gallerist-zoom-tool > button {
1377
+ min-width: calc(var(--gallerist-tool-size) - 6px * var(--_g));
1378
+ min-height: calc(var(--gallerist-tool-size) - 8px * var(--_g));
1379
+ border-radius: calc(var(--gallerist-control-radius) * (1 - var(--_g)));
1380
+ }
1381
+ /* the group's ends follow its corners */
1382
+ .gallerist-bar .gallerist-zoom-tool > :first-child {
1383
+ border-start-start-radius: var(--_r);
1384
+ border-end-start-radius: var(--_r);
1385
+ }
1386
+ .gallerist-bar .gallerist-zoom-tool > :last-child {
1387
+ border-start-end-radius: var(--_r);
1388
+ border-end-end-radius: var(--_r);
1389
+ }
1390
+ .gallerist-zoom-tool > * {
1391
+ --_r: calc(
1392
+ var(--gallerist-control-radius) *
1393
+ (1 - var(--_g)) +
1394
+ (var(--gallerist-radius) - 1px) *
1395
+ var(--_g)
1396
+ );
1397
+ }
1398
+ .gallerist-bar .gallerist-zoom-tool .gallerist-icon {
1399
+ width: calc(var(--gallerist-tool-icon) - 3px * var(--_g));
1400
+ height: calc(var(--gallerist-tool-icon) - 3px * var(--_g));
1401
+ }
1184
1402
  .gallerist-bar .gallerist-zoom-level {
1185
1403
  min-width: 4.5em;
1186
1404
  padding: 0 4px;
1187
- font: 600 13px / 1 var(--gallerist-mono);
1405
+ font: 600 calc(13px - 1px * var(--_g)) / 1 var(--gallerist-mono);
1188
1406
  font-variant-numeric: tabular-nums;
1407
+ border-inline: calc(1px * var(--_g)) solid var(--gallerist-hairline);
1189
1408
  }
1190
1409
  /* at fit there's nothing to reset: the percentage keeps its colour */
1191
1410
  .gallerist-bar .gallerist-zoom-level[aria-disabled="true"] {
@@ -2127,8 +2346,8 @@
2127
2346
  }
2128
2347
 
2129
2348
  /* the `tour` preset: the photo keeps clear of the arrows and the item navigator */
2130
- .gallerist[data-gallerist-preset="tour"][data-gallerist-frame] .gallerist-media,
2131
- .gallerist[data-gallerist-preset="tour"][data-gallerist-frame] .gallerist-media-image {
2349
+ .gallerist[data-gallerist-preset="tour"][data-gallerist-frame]
2350
+ :is(.gallerist-media, .gallerist-media-placeholder) {
2132
2351
  border-radius: 16px;
2133
2352
  }
2134
2353
 
@@ -2509,7 +2728,6 @@
2509
2728
  }
2510
2729
 
2511
2730
  @media (prefers-reduced-motion: reduce) {
2512
- .gallerist-media-image,
2513
2731
  .gallerist-bar,
2514
2732
  .gallerist-controls > button,
2515
2733
  .gallerist-itemnav,
@@ -2584,6 +2802,10 @@
2584
2802
  padding-inline: max(8px, env(safe-area-inset-left, 0px))
2585
2803
  max(8px, env(safe-area-inset-right, 0px));
2586
2804
  }
2805
+ /* the hairline before Close keeps the middle of its room (the bar's gap is 4px less here) */
2806
+ .gallerist-bar .gallerist-close::before {
2807
+ inset-inline-start: calc(2px - var(--gallerist-close-rule));
2808
+ }
2587
2809
  .gallerist-title {
2588
2810
  font-size: 13px;
2589
2811
  }
package/src/console.css CHANGED
@@ -39,7 +39,7 @@
39
39
  --gallerist-caption-band: transparent;
40
40
  --gallerist-group-bg: #1a1c1f;
41
41
  --gallerist-placeholder: rgb(255 255 255 / 0.04);
42
- --gallerist-shimmer: rgb(255 255 255 / 0.05);
42
+ --gallerist-shimmer: rgb(255 255 255 / 0.09); /* a skeleton's sweep: plain on the dark stage */
43
43
  --gallerist-shadow: 0 24px 60px rgb(0 0 0 / 0.45);
44
44
  --gallerist-stack-shadow: 3px 3px 0 -1px #3a3f46, 6px 6px 0 -2px #2a2e34;
45
45
  --gallerist-blur: none;
@@ -63,6 +63,7 @@
63
63
  --gallerist-tool-border: 0 solid transparent;
64
64
  --gallerist-tool-fg: var(--gallerist-fg-muted);
65
65
  --gallerist-tool-hover-bg: #1e2125;
66
+ --gallerist-close-rule: 9px; /* a hairline before Close */
66
67
  --gallerist-arrow-size: var(--gallerist-target);
67
68
  --gallerist-arrow-bg: var(--gallerist-chrome-bg);
68
69
  --gallerist-arrow-border: 1px solid var(--gallerist-hairline);
@@ -115,6 +116,17 @@
115
116
  --gallerist-seg-on-shadow: inset 0 1px 0 rgb(255 255 255 / 0.05), 0 1px 2px rgb(0 0 0 / 0.5);
116
117
  }
117
118
 
119
+ /* a compact bar for a mouse or trackpad (the mockup): 36px tools, 18px glyphs (Close 20px), the
120
+ zoom tool one bordered group. A touch keeps 44px targets. */
121
+ @media (pointer: fine) {
122
+ .gallerist[data-gallerist-skin="console"] {
123
+ --gallerist-tool-size: 36px;
124
+ --gallerist-tool-icon: 18px;
125
+ --gallerist-close-icon: calc(var(--gallerist-tool-icon) + 2px); /* 20px: follows the glyphs */
126
+ --gallerist-zoom-group: 1;
127
+ }
128
+ }
129
+
118
130
  /* accents */
119
131
  .gallerist[data-gallerist-skin="console"][data-gallerist-accent="cyan"] {
120
132
  --gallerist-accent-dark: #3cc8dc;
package/src/gallery.css CHANGED
@@ -36,7 +36,7 @@
36
36
  --gallerist-caption-band: transparent;
37
37
  --gallerist-group-bg: rgb(255 255 255 / 0.05);
38
38
  --gallerist-placeholder: rgb(255 255 255 / 0.04);
39
- --gallerist-shimmer: rgb(255 255 255 / 0.06);
39
+ --gallerist-shimmer: rgb(255 255 255 / 0.08);
40
40
  --gallerist-shadow: 0 16px 40px rgb(0 0 0 / 0.5);
41
41
  --gallerist-stack-shadow: 3px 3px 0 -1px #2c2c2f, 6px 6px 0 -2px #232326;
42
42
  --gallerist-blur: blur(16px) saturate(140%);