@jungherz-de/glasskit 1.19.1 → 1.21.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/CHANGELOG.md +71 -1
- package/README.md +82 -13
- package/SKILL.md +107 -5
- package/glasskit-styles.js +4 -4
- package/glasskit.css +185 -70
- package/glasskit.min.css +2 -2
- package/glasskit.min.css.map +1 -1
- package/package.json +2 -2
- package/theme-override.css +38 -0
package/glasskit.css
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
GLASSKIT COMPONENT LIBRARY
|
|
3
|
-
Jungherz GmbH – v1.
|
|
3
|
+
Jungherz GmbH – v1.21.0
|
|
4
4
|
|
|
5
5
|
Features:
|
|
6
6
|
- Scoped Reset (box-sizing fix)
|
|
7
7
|
- Dark Mode (default)
|
|
8
8
|
- Light Mode via [data-theme="light"]
|
|
9
|
+
- Compact density via [data-density="compact"]
|
|
9
10
|
- 34 components (incl. floating Tab-Bar variant + Accessory)
|
|
10
11
|
============================================================ */
|
|
11
12
|
|
|
@@ -68,6 +69,8 @@
|
|
|
68
69
|
--gl-color-text-muted: rgba(255, 255, 255, 0.60);
|
|
69
70
|
--gl-color-text-on-light: #1a3a4a;
|
|
70
71
|
--gl-color-text-heading: #ffffff;
|
|
72
|
+
/* 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");
|
|
71
74
|
--gl-color-success: #34c759;
|
|
72
75
|
--gl-color-error: #ff3b30;
|
|
73
76
|
--gl-color-warning: #ffcc00;
|
|
@@ -198,6 +201,29 @@
|
|
|
198
201
|
--gl-space-3xl: 40px;
|
|
199
202
|
--gl-space-4xl: 56px;
|
|
200
203
|
|
|
204
|
+
/* ---- Density: control sizes ----
|
|
205
|
+
The sizes GlassKit has always drawn its controls at, as tokens; the
|
|
206
|
+
rules read them with that value as fallback, like --gl-modal-max-width.
|
|
207
|
+
[data-density="compact"] (1c below) swaps in a denser set. The toggle's
|
|
208
|
+
thumb inset and travel and the first-line alignment of toggle, checkbox
|
|
209
|
+
and radio are derived from these, so any value set here stays aligned.
|
|
210
|
+
Two more are left unset on purpose, like --gl-toast-top:
|
|
211
|
+
--gl-control-padding-x (inner left and right of input, select and
|
|
212
|
+
textarea) and --gl-list-item-padding-y. Unset, the rules fall back to
|
|
213
|
+
--gl-space-md as before, so a spacing override still reaches them
|
|
214
|
+
wherever it is declared. */
|
|
215
|
+
--gl-control-height: 52px; /* input, select */
|
|
216
|
+
--gl-btn-height: 56px;
|
|
217
|
+
--gl-btn-height-sm: 44px;
|
|
218
|
+
--gl-btn-height-lg: 64px;
|
|
219
|
+
--gl-textarea-min-height: 120px;
|
|
220
|
+
--gl-list-item-min-height: 56px;
|
|
221
|
+
--gl-toggle-width: 52px;
|
|
222
|
+
--gl-toggle-height: 30px;
|
|
223
|
+
--gl-toggle-thumb-size: 22px;
|
|
224
|
+
--gl-check-size: 24px; /* checkbox, radio */
|
|
225
|
+
--gl-modal-action-height: 52px;
|
|
226
|
+
|
|
201
227
|
/* ---- Typography ---- */
|
|
202
228
|
--gl-font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
|
|
203
229
|
'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -219,6 +245,8 @@
|
|
|
219
245
|
|
|
220
246
|
/* ---- Tab-Bar ---- */
|
|
221
247
|
--gl-tab-bar-height: 82px;
|
|
248
|
+
/* Widest a .glass-modal grows; dialogs with a form or a table can take more. */
|
|
249
|
+
--gl-modal-max-width: 340px;
|
|
222
250
|
|
|
223
251
|
/* ---- Tab-Bar Floating ---- */
|
|
224
252
|
--gl-tab-bar-floating-bottom: 16px;
|
|
@@ -261,6 +289,7 @@
|
|
|
261
289
|
--gl-color-text-muted: rgba(26, 42, 54, 0.55);
|
|
262
290
|
--gl-color-text-on-light: #1a3a4a;
|
|
263
291
|
--gl-color-text-heading: #0f1f2a;
|
|
292
|
+
--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");
|
|
264
293
|
--gl-color-success: #28a745;
|
|
265
294
|
--gl-color-error: #dc3545;
|
|
266
295
|
--gl-color-warning: #e6a800;
|
|
@@ -347,6 +376,37 @@
|
|
|
347
376
|
}
|
|
348
377
|
|
|
349
378
|
|
|
379
|
+
/* ============================================================
|
|
380
|
+
1c. DESIGN TOKENS – COMPACT DENSITY
|
|
381
|
+
============================================================ */
|
|
382
|
+
/* Opt-in, next to the theme: <html data-density="compact">. Fields and
|
|
383
|
+
buttons at 40px instead of 52 and 56, smaller toggles and boxes, denser
|
|
384
|
+
list rows — for admin screens, desktop layouts and narrow forms. Only
|
|
385
|
+
the density tokens change; colours, type and spacing stay as they are.
|
|
386
|
+
|
|
387
|
+
A bare attribute selector, like [data-theme="light"]: it matches <html>,
|
|
388
|
+
and a theme wrapper that carries the attribute in a shadow root that
|
|
389
|
+
adopts the full sheet. build-styles-js.mjs moves it into tokensCss with
|
|
390
|
+
the theme blocks. It stays after them: the dark one declares the
|
|
391
|
+
defaults with the same specificity, and where both match, the later
|
|
392
|
+
block wins. */
|
|
393
|
+
[data-density="compact"] {
|
|
394
|
+
--gl-control-height: 40px;
|
|
395
|
+
--gl-control-padding-x: var(--gl-space-sm);
|
|
396
|
+
--gl-btn-height: 40px;
|
|
397
|
+
--gl-btn-height-sm: 32px;
|
|
398
|
+
--gl-btn-height-lg: 48px;
|
|
399
|
+
--gl-textarea-min-height: 88px;
|
|
400
|
+
--gl-list-item-min-height: 48px;
|
|
401
|
+
--gl-list-item-padding-y: 10px;
|
|
402
|
+
--gl-toggle-width: 44px;
|
|
403
|
+
--gl-toggle-height: 26px;
|
|
404
|
+
--gl-toggle-thumb-size: 18px;
|
|
405
|
+
--gl-check-size: 20px;
|
|
406
|
+
--gl-modal-action-height: 44px;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
350
410
|
/* ============================================================
|
|
351
411
|
2. HINTERGRUND
|
|
352
412
|
============================================================ */
|
|
@@ -519,7 +579,7 @@
|
|
|
519
579
|
============================================================ */
|
|
520
580
|
.glass-btn {
|
|
521
581
|
display: flex; align-items: center; justify-content: center;
|
|
522
|
-
gap: 10px; width: 100%; height: 56px;
|
|
582
|
+
gap: 10px; width: 100%; height: var(--gl-btn-height, 56px);
|
|
523
583
|
border: none; border-radius: var(--gl-radius-btn);
|
|
524
584
|
font-family: var(--gl-font-family);
|
|
525
585
|
font-size: var(--gl-font-size-btn);
|
|
@@ -598,8 +658,8 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
598
658
|
.glass-btn--tertiary:active { transform: translateY(1px); }
|
|
599
659
|
|
|
600
660
|
/* Sizes */
|
|
601
|
-
.glass-btn--sm { height: 44px; font-size: var(--gl-font-size-sm); border-radius: var(--gl-radius-sm); }
|
|
602
|
-
.glass-btn--lg { height: 64px; font-size: var(--gl-font-size-lg); }
|
|
661
|
+
.glass-btn--sm { height: var(--gl-btn-height-sm, 44px); font-size: var(--gl-font-size-sm); border-radius: var(--gl-radius-sm); }
|
|
662
|
+
.glass-btn--lg { height: var(--gl-btn-height-lg, 64px); font-size: var(--gl-font-size-lg); }
|
|
603
663
|
.glass-btn--auto { width: auto; padding: 0 var(--gl-space-xl); }
|
|
604
664
|
|
|
605
665
|
|
|
@@ -643,12 +703,12 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
643
703
|
font-size: var(--gl-font-size-sm);
|
|
644
704
|
font-weight: var(--gl-font-weight-medium);
|
|
645
705
|
color: var(--gl-icon-strong);
|
|
646
|
-
padding-
|
|
706
|
+
padding-inline-start: var(--gl-space-2xs);
|
|
647
707
|
}
|
|
648
708
|
|
|
649
709
|
.glass-input {
|
|
650
|
-
width: 100%; height: 52px;
|
|
651
|
-
padding: 0 var(--gl-space-md);
|
|
710
|
+
width: 100%; height: var(--gl-control-height, 52px);
|
|
711
|
+
padding: 0 var(--gl-control-padding-x, var(--gl-space-md));
|
|
652
712
|
background: var(--gl-surface-2);
|
|
653
713
|
backdrop-filter: blur(var(--gl-blur-light));
|
|
654
714
|
-webkit-backdrop-filter: blur(var(--gl-blur-light));
|
|
@@ -697,14 +757,14 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
697
757
|
.glass-hint {
|
|
698
758
|
font-size: var(--gl-font-size-xs);
|
|
699
759
|
color: var(--gl-color-text-muted);
|
|
700
|
-
padding-
|
|
760
|
+
padding-inline-start: var(--gl-space-2xs);
|
|
701
761
|
}
|
|
702
762
|
.glass-hint--error { color: var(--gl-color-error); }
|
|
703
763
|
|
|
704
764
|
/* Textarea */
|
|
705
765
|
.glass-textarea {
|
|
706
|
-
width: 100%; min-height: 120px;
|
|
707
|
-
padding: var(--gl-space-md);
|
|
766
|
+
width: 100%; min-height: var(--gl-textarea-min-height, 120px);
|
|
767
|
+
padding: var(--gl-space-md) var(--gl-control-padding-x, var(--gl-space-md));
|
|
708
768
|
background: var(--gl-surface-2);
|
|
709
769
|
backdrop-filter: blur(var(--gl-blur-light));
|
|
710
770
|
-webkit-backdrop-filter: blur(var(--gl-blur-light));
|
|
@@ -730,8 +790,8 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
730
790
|
9. SELECT
|
|
731
791
|
============================================================ */
|
|
732
792
|
.glass-select {
|
|
733
|
-
width: 100%; height: 52px;
|
|
734
|
-
padding: 0 var(--gl-space-3xl) 0 var(--gl-space-md);
|
|
793
|
+
width: 100%; height: var(--gl-control-height, 52px);
|
|
794
|
+
padding: 0 var(--gl-space-3xl) 0 var(--gl-control-padding-x, var(--gl-space-md));
|
|
735
795
|
background: var(--gl-surface-2);
|
|
736
796
|
backdrop-filter: blur(var(--gl-blur-light));
|
|
737
797
|
-webkit-backdrop-filter: blur(var(--gl-blur-light));
|
|
@@ -745,10 +805,16 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
745
805
|
box-shadow: var(--gl-inset-subtle);
|
|
746
806
|
cursor: pointer;
|
|
747
807
|
appearance: none; -webkit-appearance: none;
|
|
748
|
-
background-image: 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");
|
|
808
|
+
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"));
|
|
749
809
|
background-repeat: no-repeat;
|
|
750
810
|
background-position: right 16px center;
|
|
751
811
|
}
|
|
812
|
+
/* Right to left: the chevron and the room kept for it move to the left —
|
|
813
|
+
together, under :dir(), so a browser without it keeps both on the right. */
|
|
814
|
+
.glass-select:dir(rtl) {
|
|
815
|
+
padding: 0 var(--gl-control-padding-x, var(--gl-space-md)) 0 var(--gl-space-3xl);
|
|
816
|
+
background-position: left 16px center;
|
|
817
|
+
}
|
|
752
818
|
.glass-select:focus {
|
|
753
819
|
border-color: var(--gl-border-focus);
|
|
754
820
|
box-shadow: var(--gl-shadow-focus), var(--gl-inset-medium);
|
|
@@ -764,7 +830,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
764
830
|
}
|
|
765
831
|
|
|
766
832
|
.glass-search__icon {
|
|
767
|
-
position: absolute;
|
|
833
|
+
position: absolute; inset-inline-start: var(--gl-space-md);
|
|
768
834
|
width: 18px; height: 18px;
|
|
769
835
|
stroke: var(--gl-icon-muted) !important;
|
|
770
836
|
stroke-width: 2 !important;
|
|
@@ -776,7 +842,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
776
842
|
}
|
|
777
843
|
|
|
778
844
|
.glass-search .glass-input {
|
|
779
|
-
padding-
|
|
845
|
+
padding-inline-start: 44px;
|
|
780
846
|
border-radius: var(--gl-radius-full);
|
|
781
847
|
}
|
|
782
848
|
|
|
@@ -784,23 +850,30 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
784
850
|
/* ============================================================
|
|
785
851
|
11. TOGGLE SWITCH
|
|
786
852
|
============================================================ */
|
|
787
|
-
/* First-line alignment — see the note on .glass-checkbox below.
|
|
853
|
+
/* First-line alignment — see the note on .glass-checkbox below. The track
|
|
854
|
+
is --gl-toggle-height high (30px by default). */
|
|
788
855
|
.glass-toggle {
|
|
789
856
|
display: inline-flex; align-items: flex-start;
|
|
790
857
|
gap: var(--gl-space-sm); cursor: pointer;
|
|
791
858
|
-webkit-tap-highlight-color: transparent;
|
|
792
859
|
}
|
|
793
860
|
|
|
794
|
-
/* Visually hidden but keeps the control's area
|
|
795
|
-
browser suppress the native validation bubble
|
|
796
|
-
(silent submit block).
|
|
861
|
+
/* Visually hidden, but it keeps the control's area and lies on top of it.
|
|
862
|
+
Zero-size inputs make the browser suppress the native validation bubble
|
|
863
|
+
on required fields (silent submit block). On top, a pointer — or a test
|
|
864
|
+
tool that clicks the switch by its role — reaches the input itself; the
|
|
865
|
+
track drew over it before and took the click. It covers the track only:
|
|
866
|
+
the label text, which may hold a link, stays the label's. margin-top is
|
|
867
|
+
the track's first-line offset, from the label's font; a browser without
|
|
868
|
+
the lh unit drops it and keeps margin: 0, as the track does. */
|
|
797
869
|
.glass-toggle__input {
|
|
798
|
-
position: absolute; opacity: 0;
|
|
799
|
-
width: 52px; height: 30px;
|
|
870
|
+
position: absolute; z-index: 1; opacity: 0; cursor: inherit;
|
|
871
|
+
width: var(--gl-toggle-width, 52px); height: var(--gl-toggle-height, 30px); margin: 0; font: inherit;
|
|
872
|
+
margin-top: max(0px, calc((1lh - var(--gl-toggle-height, 30px)) / 2));
|
|
800
873
|
}
|
|
801
874
|
|
|
802
875
|
.glass-toggle__track {
|
|
803
|
-
position: relative; width: 52px; height: 30px;
|
|
876
|
+
position: relative; width: var(--gl-toggle-width, 52px); height: var(--gl-toggle-height, 30px);
|
|
804
877
|
background: var(--gl-surface-2);
|
|
805
878
|
backdrop-filter: blur(var(--gl-blur-soft));
|
|
806
879
|
-webkit-backdrop-filter: blur(var(--gl-blur-soft));
|
|
@@ -809,12 +882,19 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
809
882
|
transition: var(--gl-transition);
|
|
810
883
|
box-shadow: var(--gl-inset-subtle);
|
|
811
884
|
flex-shrink: 0;
|
|
812
|
-
margin-top: max(0px, calc((1lh - 30px) / 2));
|
|
885
|
+
margin-top: max(0px, calc((1lh - var(--gl-toggle-height, 30px)) / 2));
|
|
813
886
|
}
|
|
814
887
|
|
|
888
|
+
/* Inset and travel follow the track. Top and left (right, right to left)
|
|
889
|
+
are (height − thumb) / 2 − 1px inside the 1.5px border: 3px at 52 × 30,
|
|
890
|
+
where the thumb has always sat (taking off the whole border would move
|
|
891
|
+
it by half a pixel). It travels width − height, so the gap at the end
|
|
892
|
+
mirrors the one below. */
|
|
815
893
|
.glass-toggle__thumb {
|
|
816
|
-
position: absolute;
|
|
817
|
-
|
|
894
|
+
position: absolute;
|
|
895
|
+
top: calc((var(--gl-toggle-height, 30px) - var(--gl-toggle-thumb-size, 22px)) / 2 - 1px);
|
|
896
|
+
left: calc((var(--gl-toggle-height, 30px) - var(--gl-toggle-thumb-size, 22px)) / 2 - 1px);
|
|
897
|
+
width: var(--gl-toggle-thumb-size, 22px); height: var(--gl-toggle-thumb-size, 22px);
|
|
818
898
|
border-radius: var(--gl-radius-pill);
|
|
819
899
|
background: var(--gl-toggle-thumb-bg);
|
|
820
900
|
box-shadow: 0 2px 6px rgba(0,0,0,0.2), var(--gl-inset-milk);
|
|
@@ -829,7 +909,15 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
829
909
|
}
|
|
830
910
|
|
|
831
911
|
.glass-toggle__input:checked + .glass-toggle__track .glass-toggle__thumb {
|
|
832
|
-
transform: translateX(
|
|
912
|
+
transform: translateX(calc(var(--gl-toggle-width, 52px) - var(--gl-toggle-height, 30px)));
|
|
913
|
+
}
|
|
914
|
+
/* Right to left the thumb starts on the right and travels left — both
|
|
915
|
+
under :dir(), so a browser without it keeps the left-to-right switch. */
|
|
916
|
+
.glass-toggle__thumb:dir(rtl) {
|
|
917
|
+
left: auto; right: calc((var(--gl-toggle-height, 30px) - var(--gl-toggle-thumb-size, 22px)) / 2 - 1px);
|
|
918
|
+
}
|
|
919
|
+
.glass-toggle__input:checked + .glass-toggle__track .glass-toggle__thumb:dir(rtl) {
|
|
920
|
+
transform: translateX(calc(var(--gl-toggle-height, 30px) - var(--gl-toggle-width, 52px)));
|
|
833
921
|
}
|
|
834
922
|
|
|
835
923
|
.glass-toggle__input:focus-visible + .glass-toggle__track { box-shadow: var(--gl-shadow-focus); }
|
|
@@ -838,8 +926,12 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
838
926
|
font-size: var(--gl-font-size-base);
|
|
839
927
|
color: var(--gl-color-text);
|
|
840
928
|
user-select: none;
|
|
841
|
-
margin-top: max(0px, calc((30px - 1lh) / 2));
|
|
929
|
+
margin-top: max(0px, calc((var(--gl-toggle-height, 30px) - 1lh) / 2));
|
|
842
930
|
}
|
|
931
|
+
/* A control without a label keeps no gap for one. */
|
|
932
|
+
.glass-toggle__label:empty,
|
|
933
|
+
.glass-checkbox__label:empty,
|
|
934
|
+
.glass-radio__label:empty { display: none; }
|
|
843
935
|
|
|
844
936
|
|
|
845
937
|
/* ============================================================
|
|
@@ -847,24 +939,26 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
847
939
|
============================================================ */
|
|
848
940
|
/* Control and label are aligned on the *first line*, not on the middle of the
|
|
849
941
|
text block — a consent label runs over several lines and a centred box then
|
|
850
|
-
points at nothing. The two margins below centre the
|
|
851
|
-
line; whichever is the shorter of the two
|
|
852
|
-
ever non-zero. For a single-line label
|
|
853
|
-
`align-items: center` of pre-1.11.0.
|
|
854
|
-
.glass-
|
|
942
|
+
points at nothing. The two margins below centre the box (--gl-check-size,
|
|
943
|
+
24px by default) on that first line; whichever is the shorter of the two
|
|
944
|
+
gets the offset, so exactly one is ever non-zero. For a single-line label
|
|
945
|
+
this is pixel-identical to the `align-items: center` of pre-1.11.0.
|
|
946
|
+
Repeated on .glass-radio (--gl-check-size) and .glass-toggle
|
|
947
|
+
(--gl-toggle-height) — keep the three in step. */
|
|
855
948
|
.glass-checkbox {
|
|
856
949
|
display: inline-flex; align-items: flex-start;
|
|
857
950
|
gap: var(--gl-space-sm); cursor: pointer;
|
|
858
951
|
-webkit-tap-highlight-color: transparent;
|
|
859
952
|
}
|
|
860
|
-
/*
|
|
953
|
+
/* On top of the box, covering it only — see .glass-toggle__input. */
|
|
861
954
|
.glass-checkbox__input {
|
|
862
|
-
position: absolute; opacity: 0;
|
|
863
|
-
width: 24px; height: 24px;
|
|
955
|
+
position: absolute; z-index: 1; opacity: 0; cursor: inherit;
|
|
956
|
+
width: var(--gl-check-size, 24px); height: var(--gl-check-size, 24px); margin: 0; font: inherit;
|
|
957
|
+
margin-top: max(0px, calc((1lh - var(--gl-check-size, 24px)) / 2));
|
|
864
958
|
}
|
|
865
959
|
|
|
866
960
|
.glass-checkbox__box {
|
|
867
|
-
width: 24px; height: 24px;
|
|
961
|
+
width: var(--gl-check-size, 24px); height: var(--gl-check-size, 24px);
|
|
868
962
|
border-radius: var(--gl-radius-xs);
|
|
869
963
|
background: var(--gl-surface-2);
|
|
870
964
|
backdrop-filter: blur(var(--gl-blur-soft));
|
|
@@ -874,7 +968,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
874
968
|
transition: var(--gl-transition);
|
|
875
969
|
box-shadow: var(--gl-inset-subtle);
|
|
876
970
|
flex-shrink: 0;
|
|
877
|
-
margin-top: max(0px, calc((1lh - 24px) / 2));
|
|
971
|
+
margin-top: max(0px, calc((1lh - var(--gl-check-size, 24px)) / 2));
|
|
878
972
|
}
|
|
879
973
|
|
|
880
974
|
.glass-checkbox__box svg {
|
|
@@ -897,7 +991,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
897
991
|
.glass-checkbox__label {
|
|
898
992
|
font-size: var(--gl-font-size-base);
|
|
899
993
|
color: var(--gl-color-text); user-select: none;
|
|
900
|
-
margin-top: max(0px, calc((24px - 1lh) / 2));
|
|
994
|
+
margin-top: max(0px, calc((var(--gl-check-size, 24px) - 1lh) / 2));
|
|
901
995
|
}
|
|
902
996
|
|
|
903
997
|
|
|
@@ -910,14 +1004,15 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
910
1004
|
gap: var(--gl-space-sm); cursor: pointer;
|
|
911
1005
|
-webkit-tap-highlight-color: transparent;
|
|
912
1006
|
}
|
|
913
|
-
/*
|
|
1007
|
+
/* On top of the circle, covering it only — see .glass-toggle__input. */
|
|
914
1008
|
.glass-radio__input {
|
|
915
|
-
position: absolute; opacity: 0;
|
|
916
|
-
width: 24px; height: 24px;
|
|
1009
|
+
position: absolute; z-index: 1; opacity: 0; cursor: inherit;
|
|
1010
|
+
width: var(--gl-check-size, 24px); height: var(--gl-check-size, 24px); margin: 0; font: inherit;
|
|
1011
|
+
margin-top: max(0px, calc((1lh - var(--gl-check-size, 24px)) / 2));
|
|
917
1012
|
}
|
|
918
1013
|
|
|
919
1014
|
.glass-radio__circle {
|
|
920
|
-
width: 24px; height: 24px;
|
|
1015
|
+
width: var(--gl-check-size, 24px); height: var(--gl-check-size, 24px);
|
|
921
1016
|
border-radius: var(--gl-radius-pill);
|
|
922
1017
|
background: var(--gl-surface-2);
|
|
923
1018
|
backdrop-filter: blur(var(--gl-blur-soft));
|
|
@@ -926,7 +1021,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
926
1021
|
transition: var(--gl-transition);
|
|
927
1022
|
box-shadow: var(--gl-inset-subtle);
|
|
928
1023
|
flex-shrink: 0;
|
|
929
|
-
margin-top: max(0px, calc((1lh - 24px) / 2));
|
|
1024
|
+
margin-top: max(0px, calc((1lh - var(--gl-check-size, 24px)) / 2));
|
|
930
1025
|
}
|
|
931
1026
|
|
|
932
1027
|
.glass-radio__dot {
|
|
@@ -949,7 +1044,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
949
1044
|
.glass-radio__label {
|
|
950
1045
|
font-size: var(--gl-font-size-base);
|
|
951
1046
|
color: var(--gl-color-text); user-select: none;
|
|
952
|
-
margin-top: max(0px, calc((24px - 1lh) / 2));
|
|
1047
|
+
margin-top: max(0px, calc((var(--gl-check-size, 24px) - 1lh) / 2));
|
|
953
1048
|
}
|
|
954
1049
|
|
|
955
1050
|
|
|
@@ -1071,6 +1166,9 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1071
1166
|
);
|
|
1072
1167
|
box-shadow: 0 0 8px color-mix(in srgb, var(--gl-color-error) 30%, transparent), var(--gl-inset-strong);
|
|
1073
1168
|
}
|
|
1169
|
+
/* The fill grows from the inline start; right to left its gradient turns
|
|
1170
|
+
round so the darker end still leads. */
|
|
1171
|
+
.glass-progress__fill:dir(rtl) { scale: -1 1; }
|
|
1074
1172
|
|
|
1075
1173
|
|
|
1076
1174
|
/* ============================================================
|
|
@@ -1089,9 +1187,20 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1089
1187
|
-webkit-font-smoothing: antialiased;
|
|
1090
1188
|
}
|
|
1091
1189
|
.glass-modal-overlay.is-active { opacity: 1; pointer-events: auto; }
|
|
1190
|
+
/* The overlay may be a native <dialog>: opened with showModal() it lies in
|
|
1191
|
+
the top layer, the page behind it is inert, focus moves in and Escape
|
|
1192
|
+
closes it. These rules undo the dialog's own box and backdrop; the
|
|
1193
|
+
overlay above paints the dimmed, blurred layer. GlassKit Elements'
|
|
1194
|
+
<glk-modal> uses exactly this. */
|
|
1195
|
+
dialog.glass-modal-overlay {
|
|
1196
|
+
width: auto; height: auto; max-width: none; max-height: none;
|
|
1197
|
+
margin: 0; border: 0; color: inherit;
|
|
1198
|
+
}
|
|
1199
|
+
dialog.glass-modal-overlay:not([open]) { display: none; }
|
|
1200
|
+
dialog.glass-modal-overlay::backdrop { background: transparent; }
|
|
1092
1201
|
|
|
1093
1202
|
.glass-modal {
|
|
1094
|
-
width: 100%; max-width: 340px;
|
|
1203
|
+
width: 100%; max-width: var(--gl-modal-max-width, 340px);
|
|
1095
1204
|
background: linear-gradient(to bottom,
|
|
1096
1205
|
var(--gl-card-glow-top) 0%, var(--gl-card-glow-bottom) 100%
|
|
1097
1206
|
);
|
|
@@ -1123,7 +1232,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1123
1232
|
.glass-modal__footer { display: flex; border-top: 1px solid var(--gl-border-subtle); }
|
|
1124
1233
|
|
|
1125
1234
|
.glass-modal__action {
|
|
1126
|
-
flex: 1; height: 52px;
|
|
1235
|
+
flex: 1; height: var(--gl-modal-action-height, 52px);
|
|
1127
1236
|
background: transparent; border: none;
|
|
1128
1237
|
font-family: var(--gl-font-family);
|
|
1129
1238
|
font-size: var(--gl-font-size-btn);
|
|
@@ -1132,7 +1241,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1132
1241
|
cursor: pointer; transition: var(--gl-transition-fast); outline: none;
|
|
1133
1242
|
}
|
|
1134
1243
|
.glass-modal__action:hover { background: var(--gl-surface-1); }
|
|
1135
|
-
.glass-modal__action + .glass-modal__action { border-
|
|
1244
|
+
.glass-modal__action + .glass-modal__action { border-inline-start: 1px solid var(--gl-border-subtle); }
|
|
1136
1245
|
.glass-modal__action--primary { color: var(--gl-color-primary); font-weight: var(--gl-font-weight-semibold); }
|
|
1137
1246
|
.glass-modal__action--danger { color: var(--gl-color-error); font-weight: var(--gl-font-weight-semibold); }
|
|
1138
1247
|
|
|
@@ -1243,7 +1352,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1243
1352
|
}
|
|
1244
1353
|
.glass-toast__action:active { transform: scale(0.96); }
|
|
1245
1354
|
.glass-toast__close {
|
|
1246
|
-
width: 28px; height: 28px; margin: 0 -
|
|
1355
|
+
width: 28px; height: 28px; margin-block: 0; margin-inline: -4px -8px; padding: 0;
|
|
1247
1356
|
display: inline-flex; align-items: center; justify-content: center;
|
|
1248
1357
|
border: 0; border-radius: 50%;
|
|
1249
1358
|
background: transparent;
|
|
@@ -1327,7 +1436,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1327
1436
|
.glass-tab-bar__item:not(.is-active):hover .glass-tab-bar__label { color: var(--gl-icon-default); }
|
|
1328
1437
|
|
|
1329
1438
|
.glass-tab-bar__badge {
|
|
1330
|
-
position: absolute; top: -4px;
|
|
1439
|
+
position: absolute; top: -4px; inset-inline-end: -8px;
|
|
1331
1440
|
min-width: 16px; height: 16px; padding: 0 4px;
|
|
1332
1441
|
border-radius: var(--gl-radius-full);
|
|
1333
1442
|
/* 10px text needs 4.5:1 – white on the plain error red only reaches 3.55:1
|
|
@@ -1513,7 +1622,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1513
1622
|
font-family: var(--gl-font-family);
|
|
1514
1623
|
font-size: var(--gl-font-size-base);
|
|
1515
1624
|
font-weight: var(--gl-font-weight-semibold);
|
|
1516
|
-
color: var(--gl-color-text); text-align:
|
|
1625
|
+
color: var(--gl-color-text); text-align: start;
|
|
1517
1626
|
outline: none; transition: var(--gl-transition);
|
|
1518
1627
|
-webkit-tap-highlight-color: transparent;
|
|
1519
1628
|
}
|
|
@@ -1782,18 +1891,19 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1782
1891
|
transform-origin: bottom center;
|
|
1783
1892
|
}
|
|
1784
1893
|
.glass-popover--start {
|
|
1785
|
-
|
|
1894
|
+
inset-inline-start: 0; inset-inline-end: auto;
|
|
1786
1895
|
transform: translateY(-4px) scale(0.96);
|
|
1787
1896
|
transform-origin: top left;
|
|
1788
1897
|
}
|
|
1898
|
+
.glass-popover--start:dir(rtl) { transform-origin: top right; }
|
|
1789
1899
|
.glass-popover--start.is-open { transform: translateY(0) scale(1); }
|
|
1790
1900
|
|
|
1791
1901
|
.glass-popover--end {
|
|
1792
|
-
|
|
1793
|
-
right: 0;
|
|
1902
|
+
inset-inline-start: auto; inset-inline-end: 0;
|
|
1794
1903
|
transform: translateY(-4px) scale(0.96);
|
|
1795
1904
|
transform-origin: top right;
|
|
1796
1905
|
}
|
|
1906
|
+
.glass-popover--end:dir(rtl) { transform-origin: top left; }
|
|
1797
1907
|
.glass-popover--end.is-open { transform: translateY(0) scale(1); }
|
|
1798
1908
|
|
|
1799
1909
|
|
|
@@ -1850,15 +1960,15 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1850
1960
|
display: flex;
|
|
1851
1961
|
align-items: center;
|
|
1852
1962
|
gap: var(--gl-space-sm);
|
|
1853
|
-
padding: var(--gl-space-md) var(--gl-space-lg);
|
|
1854
|
-
min-height: 56px;
|
|
1963
|
+
padding: var(--gl-list-item-padding-y, var(--gl-space-md)) var(--gl-space-lg);
|
|
1964
|
+
min-height: var(--gl-list-item-min-height, 56px);
|
|
1855
1965
|
color: var(--gl-color-text);
|
|
1856
1966
|
font-size: var(--gl-font-size-base);
|
|
1857
1967
|
text-decoration: none;
|
|
1858
1968
|
background: transparent;
|
|
1859
1969
|
border: none;
|
|
1860
1970
|
width: 100%;
|
|
1861
|
-
text-align:
|
|
1971
|
+
text-align: start;
|
|
1862
1972
|
font-family: inherit;
|
|
1863
1973
|
list-style: none;
|
|
1864
1974
|
}
|
|
@@ -1866,20 +1976,20 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1866
1976
|
.glass-list__item:not(:last-child)::after {
|
|
1867
1977
|
content: '';
|
|
1868
1978
|
position: absolute;
|
|
1869
|
-
|
|
1870
|
-
|
|
1979
|
+
inset-inline-start: calc(var(--gl-space-lg) + 28px + var(--gl-space-sm));
|
|
1980
|
+
inset-inline-end: var(--gl-space-lg);
|
|
1871
1981
|
bottom: 0;
|
|
1872
1982
|
height: 1px;
|
|
1873
1983
|
background: var(--gl-border-subtle);
|
|
1874
1984
|
pointer-events: none;
|
|
1875
1985
|
}
|
|
1876
|
-
/* Items without a leading icon: divider follows
|
|
1877
|
-
padding instead of the
|
|
1878
|
-
.glass-list__item:not(:has(.glass-list__leading)):not(:last-child)::after {
|
|
1879
|
-
|
|
1986
|
+
/* Items without a leading icon — no slot, or a hidden one: divider follows
|
|
1987
|
+
the standard horizontal padding instead of the icon slot. */
|
|
1988
|
+
.glass-list__item:not(:has(.glass-list__leading:not([hidden]))):not(:last-child)::after {
|
|
1989
|
+
inset-inline-start: var(--gl-space-lg);
|
|
1880
1990
|
}
|
|
1881
|
-
.glass-list__item:has(.glass-list__leading--lg):not(:last-child)::after {
|
|
1882
|
-
|
|
1991
|
+
.glass-list__item:has(.glass-list__leading--lg:not([hidden])):not(:last-child)::after {
|
|
1992
|
+
inset-inline-start: calc(var(--gl-space-lg) + 40px + var(--gl-space-sm));
|
|
1883
1993
|
}
|
|
1884
1994
|
|
|
1885
1995
|
.glass-list__item--center {
|
|
@@ -1925,6 +2035,10 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
1925
2035
|
justify-content: center;
|
|
1926
2036
|
color: var(--gl-icon-strong);
|
|
1927
2037
|
}
|
|
2038
|
+
/* display: flex above beats the hidden attribute's own rule: an empty slot
|
|
2039
|
+
hidden by script kept its 28px and its gap. */
|
|
2040
|
+
.glass-list__leading[hidden],
|
|
2041
|
+
.glass-list__trailing[hidden] { display: none; }
|
|
1928
2042
|
.glass-list__leading svg,
|
|
1929
2043
|
.glass-list__leading ::slotted(svg) {
|
|
1930
2044
|
width: 24px;
|
|
@@ -2049,7 +2163,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
2049
2163
|
font-size: var(--gl-font-size-sm); color: var(--gl-color-text);
|
|
2050
2164
|
}
|
|
2051
2165
|
.glass-table th {
|
|
2052
|
-
text-align:
|
|
2166
|
+
text-align: start; padding: 8px 10px; white-space: nowrap;
|
|
2053
2167
|
font-weight: var(--gl-font-weight-medium); color: var(--gl-color-text-muted);
|
|
2054
2168
|
border-bottom: 1px solid var(--gl-border-medium);
|
|
2055
2169
|
}
|
|
@@ -2059,7 +2173,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
2059
2173
|
}
|
|
2060
2174
|
.glass-table tbody tr:last-child td { border-bottom: 0; }
|
|
2061
2175
|
.glass-table tbody tr:hover td { background: var(--gl-surface-1); }
|
|
2062
|
-
.glass-table__num { text-align:
|
|
2176
|
+
.glass-table__num { text-align: end; font-variant-numeric: tabular-nums; }
|
|
2063
2177
|
.glass-table__muted { color: var(--gl-color-text-muted); }
|
|
2064
2178
|
|
|
2065
2179
|
|
|
@@ -2085,7 +2199,7 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
2085
2199
|
.glass-prose h3 { font-size: var(--gl-font-size-lg); }
|
|
2086
2200
|
.glass-prose p, .glass-prose ul, .glass-prose ol, .glass-prose pre,
|
|
2087
2201
|
.glass-prose blockquote, .glass-prose table { margin: 0 0 0.9em; }
|
|
2088
|
-
.glass-prose ul, .glass-prose ol { padding-
|
|
2202
|
+
.glass-prose ul, .glass-prose ol { padding-inline-start: 1.3em; }
|
|
2089
2203
|
.glass-prose strong { color: var(--gl-color-text-heading); }
|
|
2090
2204
|
/* Links in running text are underlined: colour alone does not mark them. */
|
|
2091
2205
|
.glass-prose a { color: var(--gl-color-primary); text-decoration: underline; text-underline-offset: 2px; }
|
|
@@ -2100,15 +2214,16 @@ a.glass-btn { display: inline-flex; text-decoration: none; }
|
|
|
2100
2214
|
.glass-prose pre code { background: none; padding: 0; }
|
|
2101
2215
|
.glass-prose blockquote {
|
|
2102
2216
|
padding: 8px 14px;
|
|
2103
|
-
border-
|
|
2217
|
+
border-inline-start: 3px solid var(--gl-color-primary);
|
|
2104
2218
|
background: var(--gl-surface-1);
|
|
2105
|
-
border-radius: 0
|
|
2219
|
+
border-start-start-radius: 0; border-end-start-radius: 0;
|
|
2220
|
+
border-start-end-radius: var(--gl-radius-xs); border-end-end-radius: var(--gl-radius-xs);
|
|
2106
2221
|
}
|
|
2107
2222
|
.glass-prose img { max-width: 100%; height: auto; border-radius: var(--gl-radius-sm); }
|
|
2108
2223
|
.glass-prose hr { height: 1px; border: 0; margin: 1.2em 0; background: var(--gl-border-subtle); }
|
|
2109
2224
|
.glass-prose table { width: 100%; border-collapse: collapse; }
|
|
2110
2225
|
.glass-prose th, .glass-prose td {
|
|
2111
|
-
padding: 6px 8px; text-align:
|
|
2226
|
+
padding: 6px 8px; text-align: start;
|
|
2112
2227
|
border-bottom: 1px solid var(--gl-border-subtle);
|
|
2113
2228
|
}
|
|
2114
2229
|
|