@jungherz-de/glasskit 1.30.0 → 1.32.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/glasskit.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /* ============================================================
2
2
  GLASSKIT COMPONENT LIBRARY
3
- Jungherz GmbH – v1.30.0
3
+ Jungherz GmbH – v1.32.0
4
4
 
5
5
  Features:
6
6
  - Scoped Reset (box-sizing fix)
@@ -66,11 +66,13 @@
66
66
  --gl-color-bg-mid: #1a3d4e;
67
67
  --gl-color-bg-light: #1b3e50;
68
68
  --gl-color-text: #ffffff;
69
- --gl-color-text-muted: rgba(255, 255, 255, 0.60);
69
+ /* Muted text keeps 4.5:1 on the page and on glass: 65 % since 1.31.0,
70
+ before 60 % (4.45:1 on glass). The select's chevron below follows. */
71
+ --gl-color-text-muted: rgba(255, 255, 255, 0.65);
70
72
  --gl-color-text-on-light: #1a3a4a;
71
73
  --gl-color-text-heading: #ffffff;
72
74
  /* The select's chevron, drawn in the muted text colour of each theme. */
73
- --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
75
+ --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.65)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
74
76
  --gl-color-success: #34c759;
75
77
  --gl-color-error: #ff3b30;
76
78
  --gl-color-warning: #ffcc00;
@@ -311,10 +313,14 @@
311
313
  --gl-color-bg-mid: #f0f4f8;
312
314
  --gl-color-bg-light: #f5f7fa;
313
315
  --gl-color-text: #1a2a36;
314
- --gl-color-text-muted: rgba(26, 42, 54, 0.55);
316
+ /* Muted text, card text and the icons reach WCAG AA on the page and on
317
+ glass since 1.31.0: text 4.5:1 (before 3.4:1, card text 4.0:1), icons
318
+ that carry a meaning 3:1 (before 2.0:1). The icon steps, muted, default
319
+ and strong, stay in their order. */
320
+ --gl-color-text-muted: rgba(26, 42, 54, 0.68);
315
321
  --gl-color-text-on-light: #1a3a4a;
316
322
  --gl-color-text-heading: #0f1f2a;
317
- --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(26,42,54,0.55)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
323
+ --gl-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(26,42,54,0.68)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
318
324
  --gl-color-success: #28a745;
319
325
  --gl-color-error: #dc3545;
320
326
  --gl-color-warning: #e6a800;
@@ -354,8 +360,8 @@
354
360
  --gl-card-glow-low: rgba(255, 255, 255, 0.65);
355
361
  --gl-card-glow-bottom: rgba(255, 255, 255, 0.50);
356
362
 
357
- --gl-card-icon-color: rgba(26, 42, 54, 0.5);
358
- --gl-card-text-color: rgba(26, 42, 54, 0.6);
363
+ --gl-card-icon-color: rgba(26, 42, 54, 0.65);
364
+ --gl-card-text-color: rgba(26, 42, 54, 0.68);
359
365
 
360
366
  --gl-border-subtle: rgba(0, 0, 0, 0.08);
361
367
  --gl-border-medium: rgba(0, 0, 0, 0.12);
@@ -364,12 +370,12 @@
364
370
  --gl-border-warm: color-mix(in srgb, var(--gl-color-primary) 30%, transparent);
365
371
  --gl-border-focus: color-mix(in srgb, var(--gl-color-primary) 50%, transparent);
366
372
 
367
- --gl-icon-default: rgba(26, 42, 54, 0.50);
368
- --gl-icon-muted: rgba(26, 42, 54, 0.35);
369
- --gl-icon-strong: rgba(26, 42, 54, 0.70);
373
+ --gl-icon-default: rgba(26, 42, 54, 0.65);
374
+ --gl-icon-muted: rgba(26, 42, 54, 0.55);
375
+ --gl-icon-strong: rgba(26, 42, 54, 0.80);
370
376
  --gl-icon-on-primary: var(--gl-color-on-primary, #ffffff);
371
377
  --gl-icon-on-secondary: #1a3a4a;
372
- --gl-icon-on-tertiary: rgba(26, 42, 54, 0.50);
378
+ --gl-icon-on-tertiary: rgba(26, 42, 54, 0.65);
373
379
 
374
380
  --gl-shadow-card: 0 4px 20px rgba(0, 0, 0, 0.06);
375
381
  --gl-shadow-btn: 0 2px 10px rgba(0, 0, 0, 0.06);
@@ -757,10 +763,20 @@
757
763
  /* ============================================================
758
764
  6. BUTTONS
759
765
  ============================================================ */
766
+ /* Hooks of their own (since 1.31.0), as the height has --gl-btn-height:
767
+ --gl-btn-radius, unset --gl-radius-btn, which lists, the status card,
768
+ toasts, the accordion and the segmented control share, so pill-shaped
769
+ buttons no longer turn those into capsules; and --gl-btn-padding-x, the
770
+ room beside the label, unset 24px. That was the padding of --auto alone;
771
+ any other button had the browser's 6px, so a small one in a row of
772
+ actions, its width taken from its text, touched the text with its edges.
773
+ A full-width button keeps its label where it was. --sm takes
774
+ --gl-btn-radius-sm and --gl-btn-padding-x-sm, each unset the one above. */
760
775
  .glass-btn {
761
776
  display: flex; align-items: center; justify-content: center;
762
777
  gap: 10px; width: 100%; height: var(--gl-btn-height, 56px);
763
- border: none; border-radius: var(--gl-radius-btn);
778
+ padding-inline: var(--gl-btn-padding-x, var(--gl-space-xl));
779
+ border: none; border-radius: var(--gl-btn-radius, var(--gl-radius-btn));
764
780
  font-family: var(--gl-font-family);
765
781
  font-size: var(--gl-font-size-btn);
766
782
  font-weight: var(--gl-font-weight-semibold);
@@ -783,12 +799,15 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
783
799
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
784
800
  }
785
801
 
786
- /* Primary */
802
+ /* Primary. --gl-btn-primary-bg (since 1.32.0) replaces the whole
803
+ background, as the toggle and the radio have theirs: a product that keeps
804
+ white text starts the gradient darker without touching the brand colour,
805
+ which also draws focus rings, borders and the accent as text. */
787
806
  .glass-btn--primary {
788
- background: linear-gradient(135deg,
807
+ background: var(--gl-btn-primary-bg, linear-gradient(135deg,
789
808
  var(--gl-color-primary) 0%, var(--gl-color-primary-mid) 50%,
790
809
  var(--gl-color-primary-dark) 100%
791
- );
810
+ ));
792
811
  color: var(--gl-color-on-primary, #ffffff);
793
812
  border: 1px solid var(--gl-border-warm);
794
813
  box-shadow: var(--gl-shadow-btn-primary), var(--gl-inset-strong);
@@ -853,9 +872,13 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
853
872
  }
854
873
 
855
874
  /* Sizes */
856
- .glass-btn--sm { height: var(--gl-btn-height-sm, 44px); font-size: var(--gl-font-size-sm); border-radius: var(--gl-radius-sm); }
875
+ .glass-btn--sm {
876
+ height: var(--gl-btn-height-sm, 44px); font-size: var(--gl-font-size-sm);
877
+ padding-inline: var(--gl-btn-padding-x-sm, var(--gl-btn-padding-x, var(--gl-space-xl)));
878
+ border-radius: var(--gl-btn-radius-sm, var(--gl-btn-radius, var(--gl-radius-sm)));
879
+ }
857
880
  .glass-btn--lg { height: var(--gl-btn-height-lg, 64px); font-size: var(--gl-font-size-lg); }
858
- .glass-btn--auto { width: auto; padding: 0 var(--gl-space-xl); }
881
+ .glass-btn--auto { width: auto; padding-block: 0; }
859
882
 
860
883
 
861
884
  /* ============================================================
@@ -1074,7 +1097,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1074
1097
  box-shadow: var(--gl-inset-subtle);
1075
1098
  cursor: pointer;
1076
1099
  appearance: none; -webkit-appearance: none;
1077
- background-image: var(--gl-select-chevron, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.6)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"));
1100
+ background-image: var(--gl-select-chevron, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='rgba(255,255,255,0.65)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"));
1078
1101
  background-repeat: no-repeat;
1079
1102
  background-position: right 16px center;
1080
1103
  }
@@ -1316,7 +1339,9 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
1316
1339
  .glass-radio__dot {
1317
1340
  width: var(--gl-radio-dot-size, 10px); height: var(--gl-radio-dot-size, 10px);
1318
1341
  border-radius: var(--gl-radius-pill);
1319
- background: var(--gl-radio-dot-color, white);
1342
+ /* Unset, the ink on the primary (since 1.32.0), so the dot turns dark
1343
+ with the checkbox tick where a project switches the ink. */
1344
+ background: var(--gl-radio-dot-color, var(--gl-color-on-primary, white));
1320
1345
  opacity: 0; transform: scale(0);
1321
1346
  transition: var(--gl-transition-fast);
1322
1347
  }
@@ -1964,7 +1989,16 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
1964
1989
  on the item below it. Without the script a row keeps its usual look:
1965
1990
  the tab bar its spotlight, the segmented row its raised option. GlassKit
1966
1991
  Elements' <glk-tab-bar droplet> and <glk-segmented droplet> do all of
1967
- this; for plain markup the docs have the script. */
1992
+ this; for plain markup the docs have the script.
1993
+
1994
+ The motion is tokens (since 1.32.0), unset today's values, read by the
1995
+ stylesheet and the script alike: --gl-droplet-duration and -easing for
1996
+ the leading edge, -trail-duration, -trail-delay and -trail-easing for the
1997
+ trailing one, -lift (0.86; 1 squashes nothing), -lift-duration (280ms),
1998
+ -settle-duration and -settle-easing for the spring back, -lens-duration
1999
+ and -lens-easing for the item below the drop. In a column — a vertical
2000
+ tab bar, a sidebar — the script sets data-droplet-axis="y" and the
2001
+ directions "down" and "up", and the drop runs along y. */
1968
2002
  .glass-tab-bar--floating.glass-tab-bar--droplet,
1969
2003
  .glass-segmented.glass-segmented--droplet { position: relative; }
1970
2004
  .glass-tab-bar.glass-tab-bar--droplet[data-droplet],
@@ -1992,9 +2026,11 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
1992
2026
  -webkit-backdrop-filter: blur(var(--gl-blur-light)) saturate(1.6);
1993
2027
  pointer-events: none;
1994
2028
  transition:
1995
- transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
2029
+ transform var(--gl-droplet-settle-duration, 0.55s) var(--gl-droplet-settle-easing, cubic-bezier(0.34, 1.8, 0.5, 1)),
1996
2030
  box-shadow 0.3s ease;
1997
2031
  }
2032
+ /* A column hands sideways swipes to the page and keeps the vertical drag. */
2033
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-axis="y"] { touch-action: pan-x; }
1998
2034
  /* The tab bar's drop is a capsule, in the active item's surface where a
1999
2035
  project set one (--gl-tab-bar-active-bg, -shadow). */
2000
2036
  .glass-tab-bar.glass-tab-bar--droplet[data-droplet]::before {
@@ -2022,18 +2058,35 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2022
2058
  after it and overshoots, so the drop stretches and draws together. */
2023
2059
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="right"]::before {
2024
2060
  transition:
2025
- right 0.3s cubic-bezier(0.3, 1.2, 0.5, 1),
2026
- left 0.5s cubic-bezier(0.5, 1.5, 0.45, 0.92) 0.04s,
2027
- top 0.3s ease, bottom 0.3s ease,
2028
- transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
2061
+ right var(--gl-droplet-duration, 0.3s) var(--gl-droplet-easing, cubic-bezier(0.3, 1.2, 0.5, 1)),
2062
+ left var(--gl-droplet-trail-duration, 0.5s) var(--gl-droplet-trail-easing, cubic-bezier(0.5, 1.5, 0.45, 0.92)) var(--gl-droplet-trail-delay, 0.04s),
2063
+ top var(--gl-droplet-duration, 0.3s) ease, bottom var(--gl-droplet-duration, 0.3s) ease,
2064
+ transform var(--gl-droplet-settle-duration, 0.55s) var(--gl-droplet-settle-easing, cubic-bezier(0.34, 1.8, 0.5, 1)),
2029
2065
  box-shadow 0.3s ease;
2030
2066
  }
2031
2067
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="left"]::before {
2032
2068
  transition:
2033
- left 0.3s cubic-bezier(0.3, 1.2, 0.5, 1),
2034
- right 0.5s cubic-bezier(0.5, 1.5, 0.45, 0.92) 0.04s,
2035
- top 0.3s ease, bottom 0.3s ease,
2036
- transform 0.55s cubic-bezier(0.34, 1.8, 0.5, 1),
2069
+ left var(--gl-droplet-duration, 0.3s) var(--gl-droplet-easing, cubic-bezier(0.3, 1.2, 0.5, 1)),
2070
+ right var(--gl-droplet-trail-duration, 0.5s) var(--gl-droplet-trail-easing, cubic-bezier(0.5, 1.5, 0.45, 0.92)) var(--gl-droplet-trail-delay, 0.04s),
2071
+ top var(--gl-droplet-duration, 0.3s) ease, bottom var(--gl-droplet-duration, 0.3s) ease,
2072
+ transform var(--gl-droplet-settle-duration, 0.55s) var(--gl-droplet-settle-easing, cubic-bezier(0.34, 1.8, 0.5, 1)),
2073
+ box-shadow 0.3s ease;
2074
+ }
2075
+ /* In a column the same journey runs along y (since 1.32.0). */
2076
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="down"]::before {
2077
+ transition:
2078
+ bottom var(--gl-droplet-duration, 0.3s) var(--gl-droplet-easing, cubic-bezier(0.3, 1.2, 0.5, 1)),
2079
+ top var(--gl-droplet-trail-duration, 0.5s) var(--gl-droplet-trail-easing, cubic-bezier(0.5, 1.5, 0.45, 0.92)) var(--gl-droplet-trail-delay, 0.04s),
2080
+ left var(--gl-droplet-duration, 0.3s) ease, right var(--gl-droplet-duration, 0.3s) ease,
2081
+ transform var(--gl-droplet-settle-duration, 0.55s) var(--gl-droplet-settle-easing, cubic-bezier(0.34, 1.8, 0.5, 1)),
2082
+ box-shadow 0.3s ease;
2083
+ }
2084
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir="up"]::before {
2085
+ transition:
2086
+ top var(--gl-droplet-duration, 0.3s) var(--gl-droplet-easing, cubic-bezier(0.3, 1.2, 0.5, 1)),
2087
+ bottom var(--gl-droplet-trail-duration, 0.5s) var(--gl-droplet-trail-easing, cubic-bezier(0.5, 1.5, 0.45, 0.92)) var(--gl-droplet-trail-delay, 0.04s),
2088
+ left var(--gl-droplet-duration, 0.3s) ease, right var(--gl-droplet-duration, 0.3s) ease,
2089
+ transform var(--gl-droplet-settle-duration, 0.55s) var(--gl-droplet-settle-easing, cubic-bezier(0.34, 1.8, 0.5, 1)),
2037
2090
  box-shadow 0.3s ease;
2038
2091
  }
2039
2092
  /* While it travels the drop runs flatter and lifts off the row; it comes
@@ -2048,7 +2101,7 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2048
2101
  var(--gl-inset-strong);
2049
2102
  }
2050
2103
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-lift]::before {
2051
- transform: scale(1, 0.86);
2104
+ transform: scale(1, var(--gl-droplet-lift, 0.86));
2052
2105
  }
2053
2106
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before {
2054
2107
  transform: scale(1.1, 1.22);
@@ -2056,10 +2109,22 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2056
2109
  left 0.1s ease-out, right 0.1s ease-out,
2057
2110
  transform 0.25s ease-out, box-shadow 0.25s ease;
2058
2111
  }
2112
+ /* Along y the drop runs narrower instead, and grows less across its long
2113
+ side when held: a sidebar's item is wide. */
2114
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-axis="y"][data-droplet-lift]::before {
2115
+ transform: scale(var(--gl-droplet-lift, 0.86), 1);
2116
+ }
2117
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-axis="y"][data-droplet-drag]::before {
2118
+ transform: scale(1.04, 1.18);
2119
+ transition:
2120
+ top 0.1s ease-out, bottom 0.1s ease-out,
2121
+ transform 0.25s ease-out, box-shadow 0.25s ease;
2122
+ }
2059
2123
 
2060
2124
  /* The drop is the chosen item's surface, so the item draws none; on the
2061
2125
  tab bar neither spotlight, dot nor glow. */
2062
2126
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active { background: none; box-shadow: none; }
2127
+ .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active:focus-visible { box-shadow: var(--gl-shadow-focus); }
2063
2128
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active::before { display: none; }
2064
2129
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active .glass-tab-bar__icon::after { display: none; }
2065
2130
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-active .glass-tab-bar__icon > :where(:not(.glass-tab-bar__badge)),
@@ -2073,9 +2138,9 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2073
2138
  a lens. While a finger drags the drop, the item below it takes the
2074
2139
  chosen colour and the chosen item lets it go. The tab icon keeps the
2075
2140
  fade of its colour next to the lens. */
2076
- .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__icon { transition: var(--gl-transition), transform 0.4s cubic-bezier(0.34, 1.6, 0.5, 1); }
2141
+ .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__icon { transition: var(--gl-transition), transform var(--gl-droplet-lens-duration, 0.4s) var(--gl-droplet-lens-easing, cubic-bezier(0.34, 1.6, 0.5, 1)); }
2077
2142
  .glass-segmented--droplet[data-droplet] .glass-segmented__dot,
2078
- .glass-segmented--droplet[data-droplet] .glass-segmented__icon { transition: transform 0.4s cubic-bezier(0.34, 1.6, 0.5, 1); }
2143
+ .glass-segmented--droplet[data-droplet] .glass-segmented__icon { transition: transform var(--gl-droplet-lens-duration, 0.4s) var(--gl-droplet-lens-easing, cubic-bezier(0.34, 1.6, 0.5, 1)); }
2079
2144
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__item.is-under-droplet .glass-tab-bar__icon { transform: scale(1.15); }
2080
2145
  .glass-segmented--droplet[data-droplet] .glass-segmented__item.is-under-droplet .glass-segmented__dot { transform: scale(1.3); }
2081
2146
  .glass-segmented--droplet[data-droplet] .glass-segmented__item.is-under-droplet .glass-segmented__icon { transform: scale(1.15); }
@@ -2087,13 +2152,184 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2087
2152
  @media (prefers-reduced-motion: reduce) {
2088
2153
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet]::before,
2089
2154
  :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-dir]::before,
2090
- :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before { transition: none; }
2155
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-drag]::before,
2156
+ :is(.glass-tab-bar.glass-tab-bar--droplet, .glass-segmented.glass-segmented--droplet)[data-droplet][data-droplet-axis="y"][data-droplet-drag]::before { transition: none; }
2091
2157
  .glass-tab-bar--droplet[data-droplet] .glass-tab-bar__icon { transition: var(--gl-transition), transform 0s; }
2092
2158
  .glass-segmented--droplet[data-droplet] .glass-segmented__dot,
2093
2159
  .glass-segmented--droplet[data-droplet] .glass-segmented__icon { transition: none; }
2094
2160
  }
2095
2161
 
2096
2162
 
2163
+ /* ============================================================
2164
+ 18d. TAB BAR – SIDEBAR, RAIL, TOP BAR, SIDE DOCK
2165
+ ============================================================ */
2166
+ /* One navigation in more places than the bottom edge (since 1.32.0). The
2167
+ items stay the same — icon, label, badge, the active state, the drop —
2168
+ and only the bar's layout changes:
2169
+
2170
+ --vertical a column for a sidebar: placed by the page's layout (a grid
2171
+ column) and as high as its container, one item per row with
2172
+ the icon before the label at body size and the badge at the
2173
+ row's end. With --start or --end it is fixed to that edge of
2174
+ the viewport instead, full height and clear of the edge's
2175
+ safe area — the side a phone's thumb reaches when the system
2176
+ moves its own controls there. Start and end follow the
2177
+ writing direction.
2178
+ --rail with --vertical: icons alone, --gl-tab-bar-rail-width wide
2179
+ (72px). The label stays the item's name for assistive
2180
+ technology, hidden from view — show it in a tooltip — and the
2181
+ badge goes back to the icon's corner.
2182
+ --top a horizontal bar at the top: in the flow (put it in a sticky
2183
+ header), its border at the bottom, no room for the home
2184
+ indicator, and from 640px the icon beside the label.
2185
+
2186
+ The floating bar stands upright in a dock with --vertical and --start or
2187
+ --end: its items stacked as on the bottom edge, the accessory below them,
2188
+ above with --accessory-left. In a column the drop runs along y; the
2189
+ droplet script reads the flex direction. */
2190
+
2191
+ /* Every bar: a ring for the keyboard, which the items had none of. An
2192
+ item may be a link, to open a view in a new tab. */
2193
+ .glass-tab-bar__item:focus-visible { box-shadow: var(--gl-shadow-focus); }
2194
+ a.glass-tab-bar__item { text-decoration: none; color: inherit; }
2195
+
2196
+ /* ---- Sidebar ---- */
2197
+ .glass-tab-bar.glass-tab-bar--vertical {
2198
+ position: relative; inset: auto;
2199
+ height: 100%; width: auto;
2200
+ flex-direction: column; justify-content: flex-start; align-items: stretch;
2201
+ gap: var(--gl-space-2xs);
2202
+ padding: var(--gl-space-sm);
2203
+ border-top: none;
2204
+ border-inline-end: 1px solid var(--gl-border-subtle);
2205
+ overflow-y: auto; overscroll-behavior: contain;
2206
+ box-shadow: var(--gl-inset-subtle);
2207
+ }
2208
+ .glass-tab-bar--vertical .glass-tab-bar__item {
2209
+ position: relative;
2210
+ flex-direction: row; justify-content: flex-start;
2211
+ gap: var(--gl-space-sm);
2212
+ width: 100%; min-width: 0; min-height: 44px;
2213
+ padding: var(--gl-space-xs) var(--gl-space-md);
2214
+ text-align: start; text-decoration: none;
2215
+ }
2216
+ .glass-tab-bar--vertical .glass-tab-bar__label {
2217
+ flex: 1 1 auto; min-width: 0;
2218
+ font-size: var(--gl-font-size-base);
2219
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
2220
+ }
2221
+ .glass-tab-bar--vertical .glass-tab-bar__item:not(.is-active):hover { background: var(--gl-surface-1); }
2222
+ /* The active row stands on a surface of its own, unset --gl-surface-3,
2223
+ where the bottom bar has its dot. */
2224
+ .glass-tab-bar--vertical .glass-tab-bar__item.is-active { background: var(--gl-tab-bar-active-bg, var(--gl-surface-3)); }
2225
+ .glass-tab-bar--vertical .glass-tab-bar__item.is-active .glass-tab-bar__icon::after { display: none; }
2226
+ /* The badge at the row's end: positioned on the item, not the icon. */
2227
+ .glass-tab-bar--vertical:not(.glass-tab-bar--rail, .glass-tab-bar--floating) .glass-tab-bar__icon { position: static; }
2228
+ .glass-tab-bar--vertical:not(.glass-tab-bar--rail, .glass-tab-bar--floating) .glass-tab-bar__badge {
2229
+ top: 50%; inset-inline-end: var(--gl-space-md);
2230
+ transform: translateY(-50%);
2231
+ }
2232
+ /* A long label ends before the badge. */
2233
+ .glass-tab-bar--vertical:not(.glass-tab-bar--rail, .glass-tab-bar--floating) .glass-tab-bar__item:has(.glass-tab-bar__badge:not([hidden])) .glass-tab-bar__label {
2234
+ padding-inline-end: var(--gl-tab-bar-badge-room, 32px);
2235
+ }
2236
+
2237
+ /* Fixed to an edge, full height, clear of that edge's safe area. */
2238
+ .glass-tab-bar.glass-tab-bar--vertical:is(.glass-tab-bar--start, .glass-tab-bar--end) {
2239
+ position: fixed; top: 0; bottom: 0; height: auto;
2240
+ padding-top: max(var(--gl-space-sm), env(safe-area-inset-top, 0px));
2241
+ padding-bottom: max(var(--gl-space-sm), env(safe-area-inset-bottom, 0px));
2242
+ z-index: var(--gl-tab-bar-z-index, 900);
2243
+ }
2244
+ .glass-tab-bar.glass-tab-bar--vertical.glass-tab-bar--start { inset-inline-start: 0; inset-inline-end: auto; }
2245
+ .glass-tab-bar.glass-tab-bar--vertical.glass-tab-bar--end {
2246
+ inset-inline-end: 0; inset-inline-start: auto;
2247
+ border-inline-end: none; border-inline-start: 1px solid var(--gl-border-subtle);
2248
+ }
2249
+ .glass-tab-bar.glass-tab-bar--vertical:is(.glass-tab-bar--start:dir(ltr), .glass-tab-bar--end:dir(rtl)) {
2250
+ padding-left: max(var(--gl-space-sm), env(safe-area-inset-left, 0px));
2251
+ }
2252
+ .glass-tab-bar.glass-tab-bar--vertical:is(.glass-tab-bar--end:dir(ltr), .glass-tab-bar--start:dir(rtl)) {
2253
+ padding-right: max(var(--gl-space-sm), env(safe-area-inset-right, 0px));
2254
+ }
2255
+
2256
+ /* ---- Rail ---- */
2257
+ .glass-tab-bar.glass-tab-bar--vertical.glass-tab-bar--rail {
2258
+ width: var(--gl-tab-bar-rail-width, 72px);
2259
+ align-items: center;
2260
+ padding-inline: var(--gl-space-xs);
2261
+ }
2262
+ .glass-tab-bar--rail .glass-tab-bar__item {
2263
+ justify-content: center;
2264
+ width: auto; min-width: 48px; min-height: 48px;
2265
+ padding: var(--gl-space-sm);
2266
+ }
2267
+ .glass-tab-bar--rail .glass-tab-bar__label {
2268
+ position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
2269
+ overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
2270
+ }
2271
+
2272
+ /* ---- Floating, upright ---- */
2273
+ .glass-tab-bar.glass-tab-bar--floating.glass-tab-bar--vertical {
2274
+ flex-direction: column; align-items: center;
2275
+ width: auto; height: auto; max-height: 100%;
2276
+ padding: 10px 6px;
2277
+ border: 1px solid var(--gl-border-subtle);
2278
+ border-radius: var(--gl-tab-bar-floating-radius);
2279
+ }
2280
+ .glass-tab-bar--floating.glass-tab-bar--vertical .glass-tab-bar__item {
2281
+ flex-direction: column; gap: var(--gl-space-2xs);
2282
+ width: auto; min-height: 0;
2283
+ padding: var(--gl-space-2xs) var(--gl-space-sm);
2284
+ }
2285
+ .glass-tab-bar--floating.glass-tab-bar--vertical .glass-tab-bar__label {
2286
+ flex: none; font-size: var(--gl-tab-bar-label-size, 10px);
2287
+ }
2288
+ .glass-tab-bar--floating.glass-tab-bar--vertical .glass-tab-bar__item.is-active { background: var(--gl-tab-bar-active-bg, none); }
2289
+
2290
+ .glass-tab-bar-dock.glass-tab-bar-dock--vertical {
2291
+ flex-direction: column;
2292
+ top: 50%; bottom: auto;
2293
+ transform: translateY(-50%);
2294
+ max-width: none; max-height: calc(100dvh - 2 * var(--gl-space-md));
2295
+ /* The edge by the writing direction, for browsers without :dir(); the
2296
+ rules below add the safe area of the physical side. */
2297
+ left: auto; right: auto;
2298
+ inset-inline-end: calc(var(--gl-tab-bar-floating-bottom) + env(safe-area-inset-right, 0px));
2299
+ }
2300
+ .glass-tab-bar-dock.glass-tab-bar-dock--vertical.glass-tab-bar-dock--start {
2301
+ inset-inline-end: auto;
2302
+ inset-inline-start: calc(var(--gl-tab-bar-floating-bottom) + env(safe-area-inset-left, 0px));
2303
+ }
2304
+ .glass-tab-bar-dock.glass-tab-bar-dock--vertical.glass-tab-bar-dock--accessory-left { flex-direction: column-reverse; }
2305
+ /* Unset or --end, at the end edge; --start at the other. */
2306
+ .glass-tab-bar-dock.glass-tab-bar-dock--vertical:is(:not(.glass-tab-bar-dock--start):dir(ltr), .glass-tab-bar-dock--start:dir(rtl)) {
2307
+ left: auto; right: calc(var(--gl-tab-bar-floating-bottom) + env(safe-area-inset-right, 0px));
2308
+ }
2309
+ .glass-tab-bar-dock.glass-tab-bar-dock--vertical:is(.glass-tab-bar-dock--start:dir(ltr), :not(.glass-tab-bar-dock--start):dir(rtl)) {
2310
+ right: auto; left: calc(var(--gl-tab-bar-floating-bottom) + env(safe-area-inset-left, 0px));
2311
+ }
2312
+
2313
+ /* ---- Top bar ---- */
2314
+ .glass-tab-bar.glass-tab-bar--top {
2315
+ position: relative; inset: auto;
2316
+ height: auto;
2317
+ align-items: center;
2318
+ padding-bottom: var(--gl-space-xs);
2319
+ border-top: none; border-bottom: 1px solid var(--gl-border-subtle);
2320
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08), var(--gl-inset-subtle);
2321
+ }
2322
+ @media (min-width: 640px) {
2323
+ .glass-tab-bar--top .glass-tab-bar__item {
2324
+ flex-direction: row; gap: var(--gl-space-xs);
2325
+ padding-inline: var(--gl-space-md);
2326
+ }
2327
+ .glass-tab-bar--top .glass-tab-bar__label { font-size: var(--gl-font-size-sm); }
2328
+ /* Clear of the badge at the icon's corner. */
2329
+ .glass-tab-bar--top .glass-tab-bar__item:has(.glass-tab-bar__badge:not([hidden])) .glass-tab-bar__label { margin-inline-start: 8px; }
2330
+ }
2331
+
2332
+
2097
2333
  /* ============================================================
2098
2334
  19. ACCORDION
2099
2335
  ============================================================ */
@@ -2420,6 +2656,171 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2420
2656
  .glass-popover--end:dir(rtl) { transform-origin: top left; }
2421
2657
  .glass-popover--end.is-open { transform: translateY(0) scale(1); }
2422
2658
 
2659
+ /* In the top layer (since 1.32.0): with the popover attribute the panel is
2660
+ shown with showPopover() and placed by script, fixed at the coordinates
2661
+ it writes. It is no longer cut off by a box with overflow: hidden around
2662
+ it, does not leave the screen at its edges, and closed it takes no room.
2663
+ GlassKit Elements' <glk-popover> does this. */
2664
+ /* It fades out with transitions that keep it in the top layer until they
2665
+ end (transition-behavior: allow-discrete), and in with an animation —
2666
+ written in longhands and keyframes, which the minifier keeps. */
2667
+ .glass-popover[popover] {
2668
+ position: fixed; inset: auto; margin: 0;
2669
+ transform: translateY(-4px) scale(0.96);
2670
+ transition-property: opacity, transform, overlay, display;
2671
+ transition-duration: .18s;
2672
+ transition-timing-function: ease;
2673
+ transition-behavior: allow-discrete;
2674
+ }
2675
+ .glass-popover[popover]:popover-open {
2676
+ opacity: 1; visibility: visible; pointer-events: auto;
2677
+ transform: none;
2678
+ animation: glass-popover-in .22s cubic-bezier(.2,.8,.2,1);
2679
+ }
2680
+ @keyframes glass-popover-in { from { opacity: 0; transform: translateY(-4px) scale(0.96); } }
2681
+ .glass-popover[popover][data-side="top"] { transform-origin: bottom center; }
2682
+
2683
+
2684
+ /* ============================================================
2685
+ 24b. TOOLTIP
2686
+ ============================================================ */
2687
+ /* A short name or hint for a control on hover and focus (since 1.32.0):
2688
+ an icon-only button, the items of a rail, a row action. Small text on an
2689
+ opaque surface of the theme, readable over any glass, at most
2690
+ --gl-tooltip-max-width (240px) wide; --gl-tooltip-bg and
2691
+ --gl-tooltip-color recolour it. role="tooltip"; the control points to it
2692
+ with aria-describedby, or aria-labelledby where it is the control's only
2693
+ name. Opened in the top layer (popover="hint") and placed by script next
2694
+ to its control, flipped and shifted to stay in the viewport; the pointer
2695
+ can move onto it without it closing (WCAG 1.4.13). GlassKit Elements'
2696
+ <glk-tooltip> does all of this. */
2697
+ .glass-tooltip {
2698
+ max-width: var(--gl-tooltip-max-width, 240px);
2699
+ padding: 6px 12px;
2700
+ border: 1px solid var(--gl-border-medium);
2701
+ border-radius: var(--gl-radius-sm);
2702
+ /* The popover's glass, tinted far enough to keep the text readable over
2703
+ whatever lies below it. */
2704
+ background: var(--gl-tooltip-bg, color-mix(in srgb, var(--gl-color-bg-mid) 80%, transparent));
2705
+ backdrop-filter: blur(var(--gl-blur));
2706
+ -webkit-backdrop-filter: blur(var(--gl-blur));
2707
+ box-shadow: var(--gl-shadow-card), var(--gl-inset-strong);
2708
+ color: var(--gl-tooltip-color, var(--gl-color-text));
2709
+ font-family: var(--gl-font-family);
2710
+ font-size: var(--gl-font-size-xs); font-weight: var(--gl-font-weight-medium);
2711
+ line-height: 1.4;
2712
+ overflow-wrap: anywhere;
2713
+ }
2714
+ .glass-tooltip[popover] {
2715
+ inset: auto; margin: 0; overflow: visible;
2716
+ opacity: 0;
2717
+ transition-property: opacity, overlay, display;
2718
+ transition-duration: .12s;
2719
+ transition-behavior: allow-discrete;
2720
+ }
2721
+ .glass-tooltip[popover]:popover-open { opacity: 1; animation: glass-fade-in .12s ease; }
2722
+ @keyframes glass-fade-in { from { opacity: 0; } }
2723
+
2724
+
2725
+ /* ============================================================
2726
+ 24c. MENU
2727
+ ============================================================ */
2728
+ /* A list of actions behind a button (since 1.32.0): the overflow menu of a
2729
+ header, the actions of a table row. On the popover's surface, in the top
2730
+ layer and placed like the tooltip. Items are buttons with
2731
+ role="menuitem" — or menuitemcheckbox and menuitemradio with aria-checked
2732
+ (or .is-checked), which shows the check mark — with an icon before the
2733
+ label and a hint at the end, such as a shortcut. --danger takes the error
2734
+ colour for something destructive, aria-disabled="true" leaves an item
2735
+ announced but inert; __separator and __group-label part the list. The
2736
+ keyboard — arrows, Home and End, typing to jump, Escape back to the
2737
+ button — is GlassKit Elements' <glk-menu>. */
2738
+ .glass-menu {
2739
+ min-width: 180px; max-width: min(320px, calc(100vw - 16px));
2740
+ max-height: min(70vh, 480px);
2741
+ overflow-y: auto; overscroll-behavior: contain;
2742
+ padding: 6px;
2743
+ background: var(--gl-surface-3);
2744
+ backdrop-filter: blur(var(--gl-blur));
2745
+ -webkit-backdrop-filter: blur(var(--gl-blur));
2746
+ border: 1px solid var(--gl-border-medium);
2747
+ border-radius: var(--gl-radius-card);
2748
+ box-shadow: var(--gl-shadow-card), var(--gl-inset-strong);
2749
+ color: var(--gl-color-text);
2750
+ font-family: var(--gl-font-family);
2751
+ }
2752
+ .glass-menu[popover] {
2753
+ inset: auto; margin: 0;
2754
+ opacity: 0; transform: scale(0.97);
2755
+ transition-property: opacity, transform, overlay, display;
2756
+ transition-duration: .14s;
2757
+ transition-behavior: allow-discrete;
2758
+ }
2759
+ .glass-menu[popover]:popover-open { opacity: 1; transform: none; animation: glass-menu-in .14s ease; }
2760
+ @keyframes glass-menu-in { from { opacity: 0; transform: scale(0.97); } }
2761
+ .glass-menu__item {
2762
+ display: flex; align-items: center; gap: 10px;
2763
+ width: 100%; min-height: 40px;
2764
+ padding: 8px 12px;
2765
+ /* Concentric with the panel's corners. */
2766
+ border: 0; border-radius: calc(var(--gl-radius-card) - 6px);
2767
+ background: none;
2768
+ color: var(--gl-color-text);
2769
+ font: inherit; font-size: var(--gl-font-size-sm); text-align: start;
2770
+ cursor: pointer; outline: none; user-select: none;
2771
+ -webkit-tap-highlight-color: transparent;
2772
+ }
2773
+ .glass-menu__item:hover,
2774
+ .glass-menu__item:focus,
2775
+ .glass-menu__item.is-focused { background: var(--gl-surface-2); }
2776
+ .glass-menu__item:focus-visible,
2777
+ .glass-menu__item.is-focus-visible { box-shadow: inset 0 0 0 2px var(--gl-border-focus); }
2778
+ .glass-menu__item--danger { color: var(--gl-color-error-on-surface, var(--gl-color-error)); }
2779
+ .glass-menu__item[aria-disabled="true"],
2780
+ .glass-menu__item.is-disabled { opacity: 0.45; cursor: not-allowed; }
2781
+ .glass-menu__icon {
2782
+ flex: none; width: 18px; height: 18px;
2783
+ display: flex; align-items: center; justify-content: center;
2784
+ color: var(--gl-icon-default);
2785
+ }
2786
+ .glass-menu__item--danger .glass-menu__icon { color: inherit; }
2787
+ .glass-menu__icon:empty, .glass-menu__icon[hidden] { display: none; }
2788
+ .glass-menu__icon svg,
2789
+ .glass-menu__icon ::slotted(svg) {
2790
+ width: 18px; height: 18px; fill: none;
2791
+ stroke: currentColor; stroke-width: 1.8;
2792
+ stroke-linecap: round; stroke-linejoin: round;
2793
+ }
2794
+ .glass-menu__check {
2795
+ flex: none; width: 16px; height: 16px;
2796
+ color: var(--gl-color-primary-text);
2797
+ visibility: hidden;
2798
+ }
2799
+ .glass-menu__check svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
2800
+ .glass-menu__item:is([aria-checked="true"], .is-checked) .glass-menu__check { visibility: visible; }
2801
+ .glass-menu__label {
2802
+ flex: 1 1 auto; min-width: 0;
2803
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2804
+ }
2805
+ .glass-menu__trailing {
2806
+ flex: none; margin-inline-start: auto; padding-inline-start: var(--gl-space-sm);
2807
+ color: var(--gl-color-text-muted); font-size: var(--gl-font-size-xs);
2808
+ }
2809
+ .glass-menu__separator {
2810
+ height: 1px; margin: var(--gl-space-2xs) var(--gl-space-xs);
2811
+ border: 0; background: var(--gl-border-subtle);
2812
+ }
2813
+ .glass-menu__group-label {
2814
+ padding: 6px 12px 2px;
2815
+ color: var(--gl-color-text-muted);
2816
+ font-size: var(--gl-font-size-xs); font-weight: var(--gl-font-weight-semibold);
2817
+ }
2818
+ @media (prefers-reduced-motion: reduce) {
2819
+ .glass-popover[popover], .glass-popover[popover]:popover-open,
2820
+ .glass-tooltip[popover], .glass-tooltip[popover]:popover-open,
2821
+ .glass-menu[popover], .glass-menu[popover]:popover-open { transition: none; animation: none; }
2822
+ }
2823
+
2423
2824
 
2424
2825
  /* ============================================================
2425
2826
  25. LIST
@@ -2538,6 +2939,9 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2538
2939
  background: var(--gl-surface-2);
2539
2940
  outline: none;
2540
2941
  }
2942
+ /* A ring for the keyboard (since 1.32.0), inside the row: the list clips
2943
+ what lies outside it. The tint alone was too faint to find the focus. */
2944
+ .glass-list__item--interactive:focus-visible { box-shadow: inset 0 0 0 2px var(--gl-border-focus); }
2541
2945
  .glass-list__item--interactive:active {
2542
2946
  background: var(--gl-surface-3);
2543
2947
  }
@@ -2669,6 +3073,249 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2669
3073
  }
2670
3074
 
2671
3075
 
3076
+ /* ============================================================
3077
+ 25b. TREE
3078
+ ============================================================ */
3079
+ /* Levels that open and close (since 1.32.0): the structure of an app, menus
3080
+ with submenus. A row per item — a twisty that turns when the item opens,
3081
+ an icon, the label, something at the end (a badge, a status, an action) —
3082
+ indented by --gl-tree-indent (20px) per level, with the item's children
3083
+ in a __group below it. role="tree" on the container, "treeitem" on each
3084
+ item with aria-level, aria-expanded on the ones with children and
3085
+ aria-selected; one tab stop and the arrow keys of the WAI-ARIA tree view,
3086
+ which GlassKit Elements' <glk-tree> brings. No surface of its own: put it
3087
+ in a card or a sidebar. */
3088
+ .glass-tree {
3089
+ display: flex; flex-direction: column; gap: 1px;
3090
+ margin: 0; padding: 0; list-style: none;
3091
+ font-family: var(--gl-font-family);
3092
+ font-size: var(--gl-font-size-sm);
3093
+ color: var(--gl-color-text);
3094
+ }
3095
+ .glass-tree__row {
3096
+ position: relative;
3097
+ display: flex; align-items: center; gap: var(--gl-space-xs);
3098
+ min-height: var(--gl-tree-row-height, 36px);
3099
+ padding-block: 4px;
3100
+ padding-inline: calc(var(--gl-space-xs) + (var(--gl-tree-level, 1) - 1) * var(--gl-tree-indent, 20px)) var(--gl-space-sm);
3101
+ border-radius: var(--gl-radius-sm);
3102
+ cursor: pointer; user-select: none;
3103
+ transition: background .15s ease;
3104
+ }
3105
+ .glass-tree__row:hover { background: var(--gl-surface-1); }
3106
+ /* The chosen row stands on raised glass, as the active row of a sidebar
3107
+ does, its icon in the accent. */
3108
+ .glass-tree__row.is-selected {
3109
+ background: var(--gl-tree-selected-bg, var(--gl-surface-4));
3110
+ box-shadow: var(--gl-inset-strong), var(--gl-shadow-btn);
3111
+ color: var(--gl-color-text-heading);
3112
+ font-weight: var(--gl-font-weight-semibold);
3113
+ }
3114
+ .glass-tree__row.is-selected .glass-tree__icon { color: var(--gl-color-primary-text); }
3115
+ .glass-tree__row.is-focus-visible,
3116
+ .glass-tree__row:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--gl-border-focus); }
3117
+ /* In plain markup the treeitem takes the focus, its row shows it. */
3118
+ .glass-tree [role="treeitem"]:focus-visible { outline: none; }
3119
+ .glass-tree [role="treeitem"]:focus-visible > .glass-tree__row { box-shadow: inset 0 0 0 2px var(--gl-border-focus); }
3120
+ .glass-tree__row.is-disabled { opacity: 0.45; cursor: not-allowed; }
3121
+ .glass-tree__twisty {
3122
+ flex: none; width: 20px; height: 20px;
3123
+ display: flex; align-items: center; justify-content: center;
3124
+ color: var(--gl-icon-default);
3125
+ border-radius: var(--gl-radius-xs);
3126
+ transition: transform .15s ease;
3127
+ }
3128
+ .glass-tree__twisty svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
3129
+ .glass-tree__twisty:dir(rtl) { transform: scaleX(-1); }
3130
+ .glass-tree__row.is-expanded .glass-tree__twisty { transform: rotate(90deg); }
3131
+ .glass-tree__row.is-leaf .glass-tree__twisty { visibility: hidden; }
3132
+ /* Children on their way: the twisty turns into a small spinner. */
3133
+ .glass-tree__row.is-loading .glass-tree__twisty svg { display: none; }
3134
+ .glass-tree__row.is-loading .glass-tree__twisty::after {
3135
+ content: ''; width: 12px; height: 12px;
3136
+ border: 2px solid var(--gl-border-medium); border-top-color: var(--gl-color-primary);
3137
+ border-radius: 50%;
3138
+ animation: glass-tree-spin .8s linear infinite;
3139
+ }
3140
+ @keyframes glass-tree-spin { to { transform: rotate(360deg); } }
3141
+ .glass-tree__icon {
3142
+ flex: none; width: 18px; height: 18px;
3143
+ display: flex; align-items: center; justify-content: center;
3144
+ color: var(--gl-icon-default);
3145
+ }
3146
+ .glass-tree__icon:empty, .glass-tree__icon[hidden] { display: none; }
3147
+ .glass-tree__icon svg,
3148
+ .glass-tree__icon ::slotted(svg) {
3149
+ width: 18px; height: 18px; fill: none;
3150
+ stroke: currentColor; stroke-width: 1.8;
3151
+ stroke-linecap: round; stroke-linejoin: round;
3152
+ }
3153
+ .glass-tree__label {
3154
+ flex: 1 1 auto; min-width: 0;
3155
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3156
+ }
3157
+ .glass-tree__trailing {
3158
+ flex: none; display: flex; align-items: center; gap: var(--gl-space-2xs);
3159
+ margin-inline-start: auto;
3160
+ color: var(--gl-color-text-muted); font-size: var(--gl-font-size-xs);
3161
+ }
3162
+ .glass-tree__trailing[hidden] { display: none; }
3163
+ .glass-tree__group { display: flex; flex-direction: column; gap: 1px; margin: 0; padding: 0; list-style: none; }
3164
+ .glass-tree__group[hidden] { display: none; }
3165
+ /* Children that could not load: the twisty turns into a mark in the error
3166
+ colour, and opening the item again tries once more. */
3167
+ .glass-tree__row.is-error .glass-tree__twisty { color: var(--gl-color-error-on-surface, var(--gl-color-error)); }
3168
+ .glass-tree__row.is-error .glass-tree__twisty svg { display: none; }
3169
+ .glass-tree__row.is-error .glass-tree__twisty::after {
3170
+ content: '!';
3171
+ display: flex; align-items: center; justify-content: center;
3172
+ width: 14px; height: 14px; box-sizing: border-box;
3173
+ border: 1.5px solid currentColor; border-radius: 50%;
3174
+ font-size: 10px; font-weight: var(--gl-font-weight-semibold); line-height: 1;
3175
+ }
3176
+
3177
+ /* A short flash on an item that changed elsewhere — on another device, by
3178
+ an undo — so the eye finds it among the others (since 1.32.0), on a tree
3179
+ row or a list item; --gl-flash-color tints it. */
3180
+ .glass-tree__row.is-flash,
3181
+ .glass-list__item.is-flash { animation: glass-flash 1.2s ease-out; }
3182
+ @keyframes glass-flash { from { background-color: var(--gl-flash-color, color-mix(in srgb, var(--gl-color-primary) 30%, transparent)); } }
3183
+ @media (prefers-reduced-motion: reduce) {
3184
+ .glass-tree__twisty, .glass-tree__row { transition: none; }
3185
+ .glass-tree__row.is-loading .glass-tree__twisty::after { animation-duration: 2.4s; }
3186
+ .glass-tree__row.is-flash, .glass-list__item.is-flash { animation: none; }
3187
+ }
3188
+
3189
+
3190
+ /* ============================================================
3191
+ 25c. BREADCRUMBS
3192
+ ============================================================ */
3193
+ /* The path through nested levels (since 1.32.0): My app › Main menu ›
3194
+ Services › Online booking. A <nav aria-label="Breadcrumb"> around an
3195
+ <ol>; each crumb a link (or a button), the current level plain text with
3196
+ aria-current="page". The separators are drawn by CSS, hidden from
3197
+ assistive technology and mirrored right to left. A crumb longer than
3198
+ --gl-breadcrumbs-crumb-width (200px) is cut with an ellipsis. Where the
3199
+ path does not fit, __overflow stands for the middle levels — a button
3200
+ that opens them as a menu; GlassKit Elements' <glk-breadcrumbs> folds
3201
+ them by itself and makes the crumbs drop targets for a sortable list. */
3202
+ .glass-breadcrumbs { min-width: 0; font-family: var(--gl-font-family); }
3203
+ .glass-breadcrumbs__list {
3204
+ display: flex; align-items: center; flex-wrap: nowrap;
3205
+ min-width: 0; margin: 0; padding: 0; list-style: none;
3206
+ font-size: var(--gl-font-size-sm);
3207
+ }
3208
+ .glass-breadcrumbs__item { display: flex; align-items: center; min-width: 0; }
3209
+ .glass-breadcrumbs__item[hidden] { display: none; }
3210
+ .glass-breadcrumbs__item + .glass-breadcrumbs__item::before {
3211
+ content: ''; flex: none;
3212
+ width: 6px; height: 6px; margin-inline: 4px 8px;
3213
+ border-top: 1.5px solid var(--gl-icon-muted);
3214
+ border-right: 1.5px solid var(--gl-icon-muted);
3215
+ transform: rotate(45deg);
3216
+ }
3217
+ .glass-breadcrumbs__item + .glass-breadcrumbs__item:dir(rtl)::before { transform: rotate(-135deg); }
3218
+ .glass-breadcrumbs__crumb,
3219
+ .glass-breadcrumbs__current {
3220
+ display: block; min-width: 0;
3221
+ max-width: var(--gl-breadcrumbs-crumb-width, 200px);
3222
+ padding: 4px 8px;
3223
+ border-radius: var(--gl-radius-full);
3224
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3225
+ }
3226
+ .glass-breadcrumbs__crumb {
3227
+ border: 0; background: none;
3228
+ color: var(--gl-color-text-muted);
3229
+ font: inherit; text-decoration: none;
3230
+ cursor: pointer;
3231
+ transition: background .15s ease, color .15s ease;
3232
+ }
3233
+ .glass-breadcrumbs__crumb:hover { color: var(--gl-color-text); background: var(--gl-surface-1); }
3234
+ .glass-breadcrumbs__crumb:focus-visible { outline: none; box-shadow: var(--gl-shadow-focus); }
3235
+ .glass-breadcrumbs__current { color: var(--gl-color-text-heading); font-weight: var(--gl-font-weight-semibold); }
3236
+ .glass-breadcrumbs__overflow { min-width: 32px; text-align: center; letter-spacing: 1px; }
3237
+ /* The "…" crumb keeps its width where the path still does not fit. */
3238
+ .glass-breadcrumbs__item--overflow { flex: none; }
3239
+ /* A crumb as the target of a dragged item: it stands for its level. */
3240
+ .glass-breadcrumbs__crumb.is-drop-target,
3241
+ .glass-breadcrumbs__current.is-drop-target {
3242
+ color: var(--gl-color-text);
3243
+ background: color-mix(in srgb, var(--gl-color-primary) 18%, transparent);
3244
+ box-shadow: inset 0 0 0 1.5px var(--gl-border-focus);
3245
+ }
3246
+ .glass-breadcrumbs__crumb.is-drop-refused { box-shadow: inset 0 0 0 1.5px var(--gl-color-error-border); background: var(--gl-color-error-surface); }
3247
+
3248
+
3249
+ /* ============================================================
3250
+ 25d. SORTING
3251
+ ============================================================ */
3252
+ /* The states of a drag that reorders a list or a tree (since 1.32.0). The
3253
+ dragged item stays where it was, faded (.is-sort-source); a raised copy,
3254
+ __ghost, follows the pointer in the top layer. A line shows where it
3255
+ lands before or after an item — .is-sort-before / .is-sort-after on the
3256
+ target, indented to the level it lands on (--gl-tree-level) — and an
3257
+ item that takes it inside lights up (.is-sort-inside); one that refuses
3258
+ it shows the error colour (.is-sort-refused). The motion of the items
3259
+ that make room and of the drop gliding into place is GlassKit
3260
+ Elements'; --gl-sort-duration (180ms) and --gl-sort-easing (ease-out)
3261
+ time it. None of it moves under prefers-reduced-motion. */
3262
+ .is-sort-source { opacity: 0.4; }
3263
+ .is-sort-before, .is-sort-after { position: relative; }
3264
+ .is-sort-before::before,
3265
+ .is-sort-after::before {
3266
+ content: ''; position: absolute; z-index: 2;
3267
+ inset-inline-start: calc(var(--gl-space-xs) + (var(--gl-tree-level, 1) - 1) * var(--gl-tree-indent, 20px));
3268
+ inset-inline-end: var(--gl-space-xs);
3269
+ height: 2px; border-radius: 1px;
3270
+ background: var(--gl-color-primary);
3271
+ box-shadow: 0 0 6px color-mix(in srgb, var(--gl-color-primary) 50%, transparent);
3272
+ pointer-events: none;
3273
+ }
3274
+ .is-sort-before::before { top: -1px; }
3275
+ .is-sort-after::before { bottom: -1px; }
3276
+ .is-sort-inside {
3277
+ background: color-mix(in srgb, var(--gl-color-primary) 16%, transparent);
3278
+ box-shadow: inset 0 0 0 1.5px var(--gl-border-focus);
3279
+ }
3280
+ .is-sort-refused {
3281
+ background: var(--gl-color-error-surface);
3282
+ box-shadow: inset 0 0 0 1.5px var(--gl-color-error-border);
3283
+ }
3284
+ .is-sort-refused::before { background: var(--gl-color-error); box-shadow: none; }
3285
+ .glass-sort__ghost {
3286
+ display: flex; align-items: center; gap: var(--gl-space-xs);
3287
+ max-width: min(360px, calc(100vw - 16px));
3288
+ padding: 10px 14px;
3289
+ border: 1px solid var(--gl-border-medium);
3290
+ border-radius: var(--gl-radius-sm);
3291
+ background: var(--gl-surface-4);
3292
+ backdrop-filter: blur(var(--gl-blur));
3293
+ -webkit-backdrop-filter: blur(var(--gl-blur));
3294
+ box-shadow: 0 12px 32px rgba(0,0,0,0.28), 0 2px 8px rgba(0,0,0,0.14), var(--gl-inset-strong);
3295
+ color: var(--gl-color-text);
3296
+ font-family: var(--gl-font-family); font-size: var(--gl-font-size-sm);
3297
+ font-weight: var(--gl-font-weight-medium);
3298
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
3299
+ pointer-events: none;
3300
+ }
3301
+ .glass-sort__ghost[popover] { inset: auto; margin: 0; overflow: hidden; }
3302
+ /* Closed, out of the page: its own display would keep it on screen. */
3303
+ .glass-sort__ghost[popover]:not(:popover-open) { display: none; }
3304
+ /* A handle: with one, only the handle starts a drag, so a tap on the item
3305
+ still chooses it; a finger on it drags at once, without the long press. */
3306
+ .glass-sort__handle {
3307
+ flex: none; display: flex; align-items: center; justify-content: center;
3308
+ color: var(--gl-icon-muted);
3309
+ cursor: grab; touch-action: none;
3310
+ }
3311
+ .glass-sort__handle[hidden] { display: none; }
3312
+ .glass-sort__handle svg,
3313
+ .glass-sort__handle ::slotted(svg) {
3314
+ width: 18px; height: 18px; fill: none;
3315
+ stroke: currentColor; stroke-width: 1.8; stroke-linecap: round;
3316
+ }
3317
+
3318
+
2672
3319
  /* ============================================================
2673
3320
  26. SKELETON
2674
3321
  ============================================================ */
@@ -2708,12 +3355,12 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2708
3355
  font-size: var(--gl-font-size-sm); color: var(--gl-color-text);
2709
3356
  }
2710
3357
  .glass-table th {
2711
- text-align: start; padding: 8px 10px; white-space: nowrap;
3358
+ text-align: start; padding: var(--gl-table-header-padding, 8px 10px); white-space: nowrap;
2712
3359
  font-weight: var(--gl-font-weight-medium); color: var(--gl-color-text-muted);
2713
3360
  border-bottom: 1px solid var(--gl-border-medium);
2714
3361
  }
2715
3362
  .glass-table td {
2716
- padding: 9px 10px; vertical-align: top;
3363
+ padding: var(--gl-table-cell-padding, 9px 10px); vertical-align: top;
2717
3364
  border-bottom: 1px solid var(--gl-border-subtle);
2718
3365
  }
2719
3366
  .glass-table tbody tr:last-child td { border-bottom: 0; }
@@ -2721,6 +3368,131 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2721
3368
  .glass-table__num { text-align: end; font-variant-numeric: tabular-nums; }
2722
3369
  .glass-table__muted { color: var(--gl-color-text-muted); }
2723
3370
 
3371
+ /* More since 1.32.0, mostly brought by GlassKit Elements' <glk-table>
3372
+ around the table, which keeps it a native table in the page:
3373
+
3374
+ __sort a button filling a header cell that sorts by its column;
3375
+ the th carries aria-sort and the arrow shows it.
3376
+ --sticky the header cells stick to the top of a wrap that scrolls
3377
+ both ways (.glass-table-wrap--sticky, as high as
3378
+ --gl-table-max-height, 60vh), on --gl-table-header-bg.
3379
+ __actions a cell for row actions — a menu, icon buttons — at the
3380
+ row's end, kept there while the table scrolls sideways
3381
+ (on a surface of its own once it does: --scrolls).
3382
+ --list each row a card with the column's name before each value
3383
+ (data-label on the cells), the actions at its top end —
3384
+ for narrow places.
3385
+
3386
+ --gl-table-cell-padding and --gl-table-header-padding set the cells'
3387
+ room. */
3388
+ .glass-table__sort {
3389
+ display: inline-flex; align-items: center; gap: 4px;
3390
+ margin: -4px -6px; padding: 4px 6px;
3391
+ border: 0; border-radius: var(--gl-radius-xs);
3392
+ background: none; color: inherit;
3393
+ font: inherit; font-weight: inherit; white-space: nowrap;
3394
+ cursor: pointer;
3395
+ transition: background .15s ease, color .15s ease;
3396
+ }
3397
+ .glass-table__sort:hover { color: var(--gl-color-text); background: var(--gl-surface-1); }
3398
+ .glass-table__sort:focus-visible { outline: none; box-shadow: var(--gl-shadow-focus); }
3399
+ .glass-table__sort-icon {
3400
+ flex: none; width: 12px; height: 12px;
3401
+ fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
3402
+ opacity: 0.35;
3403
+ transition: transform .15s ease, opacity .15s ease;
3404
+ }
3405
+ .glass-table th:is([aria-sort="ascending"], [aria-sort="descending"]) .glass-table__sort { color: var(--gl-color-text); }
3406
+ .glass-table th:is([aria-sort="ascending"], [aria-sort="descending"]) .glass-table__sort-icon { opacity: 1; }
3407
+ .glass-table th[aria-sort="descending"] .glass-table__sort-icon { transform: rotate(180deg); }
3408
+
3409
+ .glass-table-wrap--sticky { overflow: auto; max-height: var(--gl-table-max-height, 60vh); overscroll-behavior: contain; }
3410
+ .glass-table--sticky thead th {
3411
+ position: sticky; top: 0; z-index: 2;
3412
+ /* The line goes with the cell: a collapsed border stays with the table. */
3413
+ border-bottom: 0;
3414
+ box-shadow: inset 0 -1px 0 var(--gl-border-medium);
3415
+ background: var(--gl-table-header-bg, color-mix(in srgb, var(--gl-color-bg-mid) 94%, transparent));
3416
+ backdrop-filter: blur(var(--gl-blur-light));
3417
+ -webkit-backdrop-filter: blur(var(--gl-blur-light));
3418
+ }
3419
+
3420
+ .glass-table__actions {
3421
+ position: sticky; inset-inline-end: 0; z-index: 1;
3422
+ width: 1%; text-align: end; white-space: nowrap;
3423
+ }
3424
+ .glass-table--sticky thead th.glass-table__actions { z-index: 3; }
3425
+ .glass-table--scrolls .glass-table__actions {
3426
+ background: var(--gl-table-header-bg, color-mix(in srgb, var(--gl-color-bg-mid) 94%, transparent));
3427
+ box-shadow: -8px 0 8px -8px rgba(0,0,0,0.3);
3428
+ }
3429
+ .glass-table--scrolls .glass-table__actions:dir(rtl) { box-shadow: 8px 0 8px -8px rgba(0,0,0,0.3); }
3430
+
3431
+ /* The edges of a wrap that scrolls sideways shade where more columns wait
3432
+ (data-more-start, data-more-end on the frame, set by <glk-table>). */
3433
+ .glass-table-frame { position: relative; min-width: 0; }
3434
+ .glass-table-frame::before,
3435
+ .glass-table-frame::after {
3436
+ content: ''; position: absolute; top: 0; bottom: 0; z-index: 4;
3437
+ width: 16px; pointer-events: none;
3438
+ opacity: 0; transition: opacity .15s ease;
3439
+ }
3440
+ .glass-table-frame::before { inset-inline-start: 0; background: linear-gradient(to right, rgba(0,0,0,0.22), transparent); }
3441
+ .glass-table-frame::after { inset-inline-end: 0; background: linear-gradient(to left, rgba(0,0,0,0.22), transparent); }
3442
+ .glass-table-frame:dir(rtl)::before { background: linear-gradient(to left, rgba(0,0,0,0.22), transparent); }
3443
+ .glass-table-frame:dir(rtl)::after { background: linear-gradient(to right, rgba(0,0,0,0.22), transparent); }
3444
+ .glass-table-frame[data-more-start]::before,
3445
+ .glass-table-frame[data-more-end]::after { opacity: 1; }
3446
+ .glass-table__empty { padding: var(--gl-space-lg) var(--gl-space-md); }
3447
+ .glass-table__empty[hidden] { display: none; }
3448
+
3449
+ /* As cards. The header stays for assistive technology, hidden from view;
3450
+ the labels are generated content without a text of their own, so a
3451
+ screen reader does not hear the column twice. */
3452
+ .glass-table--list thead {
3453
+ position: absolute; width: 1px; height: 1px; margin: -1px;
3454
+ overflow: hidden; clip-path: inset(50%); white-space: nowrap;
3455
+ }
3456
+ .glass-table--list,
3457
+ .glass-table--list tbody,
3458
+ .glass-table--list tr,
3459
+ .glass-table--list td { display: block; width: 100%; box-sizing: border-box; }
3460
+ .glass-table--list tbody { display: flex; flex-direction: column; gap: var(--gl-space-sm); }
3461
+ .glass-table--list tr {
3462
+ position: relative;
3463
+ display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--gl-space-sm);
3464
+ padding: var(--gl-space-sm) var(--gl-space-md);
3465
+ border: 1px solid var(--gl-border-subtle);
3466
+ /* Glass like the list's and the accordion's items. */
3467
+ border-radius: var(--gl-radius-btn);
3468
+ background: var(--gl-surface-1);
3469
+ box-shadow: var(--gl-inset-subtle);
3470
+ }
3471
+ .glass-table--list td {
3472
+ display: flex; justify-content: space-between; align-items: baseline; gap: var(--gl-space-md);
3473
+ grid-column: 1 / -1;
3474
+ padding: 4px 0; border: 0;
3475
+ text-align: end; overflow-wrap: anywhere;
3476
+ }
3477
+ /* The actions at the card's top end, beside its first two values. */
3478
+ .glass-table--list tr:has(> .glass-table__actions) > td:nth-child(-n+2):not(.glass-table__actions) { grid-column: 1; }
3479
+ .glass-table--list td::before {
3480
+ content: attr(data-label);
3481
+ content: attr(data-label) / "";
3482
+ flex: none; max-width: 50%;
3483
+ color: var(--gl-color-text-muted); font-weight: var(--gl-font-weight-medium);
3484
+ text-align: start;
3485
+ }
3486
+ .glass-table--list td:is(:not([data-label]), [data-label=""])::before { content: none; }
3487
+ .glass-table--list tbody tr:hover td { background: none; }
3488
+ .glass-table--list .glass-table__actions {
3489
+ position: static; grid-column: 2; grid-row: 1 / span 2; align-self: start;
3490
+ width: auto; padding: 0; background: none; box-shadow: none;
3491
+ }
3492
+ @media (prefers-reduced-motion: reduce) {
3493
+ .glass-table__sort, .glass-table__sort-icon, .glass-table-frame::before, .glass-table-frame::after { transition: none; }
3494
+ }
3495
+
2724
3496
 
2725
3497
  /* ============================================================
2726
3498
  28. PROSE
@@ -2878,17 +3650,22 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2878
3650
  the place for an --icons row. There it covers the icon, so the theme's
2879
3651
  middle background goes underneath (--gl-segmented-badge-base, the
2880
3652
  badge's background colour). Its number is no name: give the option an
2881
- aria-label such as "Tickets, 1 open". */
3653
+ aria-label such as "Tickets, 1 open". Since 1.31.0 its size and the
3654
+ hairline of the neutral count are tokens: --gl-segmented-badge-height
3655
+ (unset 16px, also the least width), --gl-segmented-badge-font-size
3656
+ (unset 11px) and --gl-segmented-badge-border (a colour, unset none,
3657
+ drawn inside, so the count keeps its size). */
2882
3658
  .glass-segmented__badge {
2883
3659
  flex: none;
2884
3660
  display: inline-flex; align-items: center; justify-content: center;
2885
- min-width: 16px; height: 16px; padding: 0 5px;
3661
+ min-width: var(--gl-segmented-badge-height, 16px); height: var(--gl-segmented-badge-height, 16px); padding: 0 5px;
2886
3662
  border-radius: var(--gl-radius-full);
2887
3663
  background-color: var(--gl-segmented-badge-base, var(--gl-state-scrim, transparent));
2888
3664
  background-image: linear-gradient(var(--gl-segmented-badge-bg, color-mix(in srgb, var(--gl-color-text) 12%, transparent)),
2889
3665
  var(--gl-segmented-badge-bg, color-mix(in srgb, var(--gl-color-text) 12%, transparent)));
3666
+ box-shadow: inset 0 0 0 1px var(--gl-segmented-badge-border, transparent);
2890
3667
  color: var(--gl-segmented-badge-color, var(--gl-color-text));
2891
- font-size: 11px; font-weight: var(--gl-font-weight-semibold);
3668
+ font-size: var(--gl-segmented-badge-font-size, 11px); font-weight: var(--gl-font-weight-semibold);
2892
3669
  font-variant-numeric: tabular-nums;
2893
3670
  line-height: 1;
2894
3671
  }
@@ -2910,6 +3687,36 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2910
3687
  box-shadow: inset 0 0 0 1px var(--gl-color-error-border);
2911
3688
  color: var(--gl-color-error-on-surface, var(--gl-color-error));
2912
3689
  }
3690
+ /* A colour of the count's own (since 1.31.0), whatever the option's tone:
3691
+ --primary, --success, --warning and --error give it the look of
3692
+ .glass-badge's variants (the state tint over a doubled scrim, a hairline,
3693
+ the readable text colour), without the dot a tone puts before the label.
3694
+ After the tones of the option, so the count's own colour wins where both
3695
+ are set. */
3696
+ .glass-segmented__badge.glass-segmented__badge--primary {
3697
+ background-image: linear-gradient(var(--gl-color-primary-surface), var(--gl-color-primary-surface)),
3698
+ linear-gradient(var(--gl-state-scrim), var(--gl-state-scrim));
3699
+ box-shadow: inset 0 0 0 1px var(--gl-color-primary-border);
3700
+ color: var(--gl-color-primary-on-surface, var(--gl-color-primary));
3701
+ }
3702
+ .glass-segmented__badge.glass-segmented__badge--success {
3703
+ background-image: linear-gradient(var(--gl-color-success-surface), var(--gl-color-success-surface)),
3704
+ linear-gradient(var(--gl-state-scrim), var(--gl-state-scrim));
3705
+ box-shadow: inset 0 0 0 1px var(--gl-color-success-border);
3706
+ color: var(--gl-color-success-on-surface, var(--gl-color-success));
3707
+ }
3708
+ .glass-segmented__badge.glass-segmented__badge--warning {
3709
+ background-image: linear-gradient(var(--gl-color-warning-surface), var(--gl-color-warning-surface)),
3710
+ linear-gradient(var(--gl-state-scrim), var(--gl-state-scrim));
3711
+ box-shadow: inset 0 0 0 1px var(--gl-color-warning-border);
3712
+ color: var(--gl-color-warning-on-surface, var(--gl-color-warning));
3713
+ }
3714
+ .glass-segmented__badge.glass-segmented__badge--error {
3715
+ background-image: linear-gradient(var(--gl-color-error-surface), var(--gl-color-error-surface)),
3716
+ linear-gradient(var(--gl-state-scrim), var(--gl-state-scrim));
3717
+ box-shadow: inset 0 0 0 1px var(--gl-color-error-border);
3718
+ color: var(--gl-color-error-on-surface, var(--gl-color-error));
3719
+ }
2913
3720
  .glass-segmented__icon > .glass-segmented__badge {
2914
3721
  --gl-segmented-badge-base: var(--gl-color-bg-mid);
2915
3722
  position: absolute; top: -4px; inset-inline-end: -8px;
@@ -2955,8 +3762,11 @@ dialog.glass-modal-overlay::backdrop { background: transparent; }
2955
3762
  color: var(--gl-color-success-on-surface);
2956
3763
  }
2957
3764
  .glass-steps__item--current { color: var(--gl-color-text-heading); }
3765
+ /* The flat accent fills that carry text — this number, the chosen day of
3766
+ the date strip and of the calendar — take --gl-color-primary-fill where
3767
+ it is set (since 1.32.0), else the primary. */
2958
3768
  .glass-steps__item--current .glass-steps__num {
2959
- background: var(--gl-color-primary); border-color: transparent;
3769
+ background: var(--gl-color-primary-fill, var(--gl-color-primary)); border-color: transparent;
2960
3770
  color: var(--gl-color-on-primary);
2961
3771
  }
2962
3772
  .glass-steps__line { flex: 1 1 8px; min-width: 8px; height: 1px; background: var(--gl-border-subtle); }
@@ -3129,7 +3939,7 @@ dialog.glass-sheet-overlay::backdrop { background: transparent; }
3129
3939
  .glass-date-strip__day:hover { background: var(--gl-surface-3); }
3130
3940
  .glass-date-strip__day[aria-pressed="true"] {
3131
3941
  --gl-date-strip-ink: var(--gl-color-on-primary);
3132
- background: var(--gl-color-primary);
3942
+ background: var(--gl-color-primary-fill, var(--gl-color-primary));
3133
3943
  color: var(--gl-color-on-primary);
3134
3944
  border-color: transparent;
3135
3945
  box-shadow: var(--gl-shadow-btn-primary);
@@ -3146,6 +3956,10 @@ dialog.glass-sheet-overlay::backdrop { background: transparent; }
3146
3956
  font-size: var(--gl-font-size-xs); opacity: 0.75;
3147
3957
  text-transform: uppercase; letter-spacing: 0.04em;
3148
3958
  }
3959
+ /* On the chosen chip the weekday is as strong as the number (since
3960
+ 1.32.0): faded, it stayed below 4.5:1 even on a fill that the number
3961
+ reaches it on. */
3962
+ .glass-date-strip__day[aria-pressed="true"] .glass-date-strip__wd { opacity: 1; }
3149
3963
  .glass-date-strip__num {
3150
3964
  font-size: var(--gl-font-size-lg); font-weight: var(--gl-font-weight-semibold);
3151
3965
  line-height: 1.1;
@@ -3235,7 +4049,7 @@ dialog.glass-sheet-overlay::backdrop { background: transparent; }
3235
4049
  .glass-calendar__day--today { border-color: var(--gl-border-warm); }
3236
4050
  .glass-calendar__day[aria-pressed="true"] {
3237
4051
  --gl-calendar-ink: var(--gl-color-on-primary);
3238
- background: var(--gl-color-primary);
4052
+ background: var(--gl-color-primary-fill, var(--gl-color-primary));
3239
4053
  color: var(--gl-color-on-primary);
3240
4054
  }
3241
4055
  .glass-calendar__day:focus-visible { box-shadow: var(--gl-shadow-focus); }