@hearthsound/design 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -2
  3. package/THIRD-PARTY.md +46 -0
  4. package/css/base.css +245 -0
  5. package/css/components/admin.css +257 -0
  6. package/css/components/banner.css +140 -0
  7. package/css/components/button.css +309 -0
  8. package/css/components/card.css +339 -0
  9. package/css/components/check.css +202 -0
  10. package/css/components/dialog.css +85 -0
  11. package/css/components/field.css +298 -0
  12. package/css/components/list.css +260 -0
  13. package/css/components/menu.css +335 -0
  14. package/css/components/page-header.css +230 -0
  15. package/css/components/pill.css +101 -0
  16. package/css/components/player.css +524 -0
  17. package/css/components/progress.css +173 -0
  18. package/css/components/section.css +86 -0
  19. package/css/components/segmented.css +64 -0
  20. package/css/components/shell.css +281 -0
  21. package/css/components/sidebar.css +170 -0
  22. package/css/components/slider.css +92 -0
  23. package/css/components/status-page.css +48 -0
  24. package/css/components/stepper.css +130 -0
  25. package/css/components/toast.css +88 -0
  26. package/css/components/tooltip.css +29 -0
  27. package/css/components/track.css +336 -0
  28. package/css/components/upload.css +70 -0
  29. package/css/index.css +35 -0
  30. package/css/tokens.css +375 -0
  31. package/dist/icons.d.ts +56 -0
  32. package/dist/icons.js +56 -0
  33. package/dist/icons.svg +55 -0
  34. package/fonts/OFL-BricolageGrotesque.txt +93 -0
  35. package/fonts/OFL-Geist.txt +92 -0
  36. package/fonts/bricolage-var.woff2 +0 -0
  37. package/fonts/geist-mono.woff2 +0 -0
  38. package/fonts/geist-var.woff2 +0 -0
  39. package/icons/LICENSE +10 -0
  40. package/icons/adwaita-account.svg +1 -0
  41. package/icons/adwaita-acquire.svg +1 -0
  42. package/icons/adwaita-add.svg +1 -0
  43. package/icons/adwaita-album.svg +1 -0
  44. package/icons/adwaita-artist.svg +1 -0
  45. package/icons/adwaita-back.svg +1 -0
  46. package/icons/adwaita-check.svg +1 -0
  47. package/icons/adwaita-close.svg +1 -0
  48. package/icons/adwaita-collapse.svg +1 -0
  49. package/icons/adwaita-dark-mode.svg +1 -0
  50. package/icons/adwaita-delete.svg +1 -0
  51. package/icons/adwaita-drag.svg +1 -0
  52. package/icons/adwaita-edit.svg +1 -0
  53. package/icons/adwaita-error.svg +1 -0
  54. package/icons/adwaita-expand.svg +1 -0
  55. package/icons/adwaita-folder.svg +1 -0
  56. package/icons/adwaita-forward.svg +1 -0
  57. package/icons/adwaita-home.svg +1 -0
  58. package/icons/adwaita-layers.svg +1 -0
  59. package/icons/adwaita-like.svg +1 -0
  60. package/icons/adwaita-lock.svg +1 -0
  61. package/icons/adwaita-menu.svg +1 -0
  62. package/icons/adwaita-more.svg +1 -0
  63. package/icons/adwaita-mute.svg +1 -0
  64. package/icons/adwaita-next.svg +1 -0
  65. package/icons/adwaita-pause.svg +1 -0
  66. package/icons/adwaita-play.svg +1 -0
  67. package/icons/adwaita-playlist.svg +1 -0
  68. package/icons/adwaita-plugin.svg +1 -0
  69. package/icons/adwaita-previous.svg +1 -0
  70. package/icons/adwaita-queue.svg +1 -0
  71. package/icons/adwaita-rating-outline.svg +1 -0
  72. package/icons/adwaita-rating.svg +1 -0
  73. package/icons/adwaita-refresh.svg +1 -0
  74. package/icons/adwaita-remote.svg +1 -0
  75. package/icons/adwaita-remove.svg +1 -0
  76. package/icons/adwaita-repeat.svg +1 -0
  77. package/icons/adwaita-reveal.svg +1 -0
  78. package/icons/adwaita-search.svg +1 -0
  79. package/icons/adwaita-settings.svg +1 -0
  80. package/icons/adwaita-shuffle.svg +1 -0
  81. package/icons/adwaita-sign-out.svg +1 -0
  82. package/icons/adwaita-song.svg +1 -0
  83. package/icons/adwaita-sort.svg +1 -0
  84. package/icons/adwaita-storage.svg +1 -0
  85. package/icons/adwaita-users.svg +1 -0
  86. package/icons/adwaita-volume.svg +1 -0
  87. package/icons/adwaita-warning.svg +1 -0
  88. package/icons/custom-dislike-outline.svg +1 -0
  89. package/icons/custom-dislike.svg +1 -0
  90. package/icons/custom-like-outline.svg +1 -0
  91. package/icons/custom-unknown.svg +1 -0
  92. package/icons/custom-upload.svg +1 -0
  93. package/identity/icons/app-icon-dark-16.png +0 -0
  94. package/identity/icons/app-icon-dark-180.png +0 -0
  95. package/identity/icons/app-icon-dark-192.png +0 -0
  96. package/identity/icons/app-icon-dark-32.png +0 -0
  97. package/identity/icons/app-icon-dark-512.png +0 -0
  98. package/identity/icons/app-icon-dark.svg +1 -0
  99. package/identity/icons/app-icon-light-16.png +0 -0
  100. package/identity/icons/app-icon-light-180.png +0 -0
  101. package/identity/icons/app-icon-light-192.png +0 -0
  102. package/identity/icons/app-icon-light-32.png +0 -0
  103. package/identity/icons/app-icon-light-512.png +0 -0
  104. package/identity/icons/app-icon-light.svg +1 -0
  105. package/identity/icons/favicon.svg +1 -0
  106. package/identity/mark/mark-dark.svg +1 -0
  107. package/identity/mark/mark-light.svg +1 -0
  108. package/identity/mark/mark-symbolic.svg +1 -0
  109. package/package.json +35 -4
@@ -0,0 +1,339 @@
1
+ /*
2
+ * @hearthsound/design - cards
3
+ *
4
+ * k13 C album card, k14 B artist card, k15 playlist card, k16 C mosaic,
5
+ * f15b missing art, l10 admin Overview cards, p18 Top Result card.
6
+ * Values from shared/approved/components.css (.ac, .mos, .dash, .acard,
7
+ * p18 page CSS) and spec/components.md.
8
+ */
9
+
10
+ /* ------------------------------------------------------------------ */
11
+ /* k13 / k14 / k15 - cards */
12
+ /* ------------------------------------------------------------------ */
13
+
14
+ .hs-card {
15
+ position: relative;
16
+ padding: 8px;
17
+ margin: -8px;
18
+ border-radius: var(--hs-radius-card);
19
+ color: var(--hs-fg);
20
+ font: 400 14px/1.35 var(--hs-font-body);
21
+ container-type: inline-size;
22
+ transition: background var(--hs-duration-hover) var(--hs-ease);
23
+ }
24
+
25
+ /* The card link covers the whole tile; the play disc is a separate target
26
+ * above it, reachable with Tab after the card (k13). */
27
+ .hs-card__link {
28
+ position: absolute;
29
+ inset: 0;
30
+ z-index: 1;
31
+ border-radius: inherit;
32
+ color: inherit;
33
+ text-decoration: none;
34
+ }
35
+
36
+ .hs-card:has(.hs-card__link:focus-visible) {
37
+ outline: none;
38
+ background: var(--hs-accent-tint);
39
+ }
40
+
41
+ .hs-card__cover {
42
+ position: relative;
43
+ display: block;
44
+ aspect-ratio: 1;
45
+ border-radius: var(--hs-radius-art);
46
+ transition: transform var(--hs-duration-hover) var(--hs-ease),
47
+ box-shadow var(--hs-duration-hover) var(--hs-ease);
48
+ }
49
+
50
+ .hs-card__cover img {
51
+ width: 100%;
52
+ height: 100%;
53
+ border-radius: inherit;
54
+ display: block;
55
+ object-fit: cover;
56
+ }
57
+
58
+ /* f15b - tonal tile with the centred icon at 36% (minimum 14 px). */
59
+ .hs-art-placeholder {
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ width: 100%;
64
+ height: 100%;
65
+ border-radius: inherit;
66
+ background: var(--hs-art-placeholder-bg);
67
+ color: var(--hs-fg-muted);
68
+ }
69
+
70
+ .hs-art-placeholder .hs-icon {
71
+ --hs-icon-size: 36%;
72
+ min-width: 14px;
73
+ min-height: 14px;
74
+ opacity: 0.8;
75
+ }
76
+
77
+ .hs-card__text {
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 2px;
81
+ min-width: 0;
82
+ }
83
+
84
+ .hs-card__title {
85
+ font-weight: 600;
86
+ display: -webkit-box;
87
+ -webkit-line-clamp: 2;
88
+ -webkit-box-orient: vertical;
89
+ overflow: hidden;
90
+ }
91
+
92
+ .hs-card__artist {
93
+ color: var(--hs-fg-muted);
94
+ font-size: 13px;
95
+ }
96
+
97
+ /* Play disc: 44 px acid disc at the cover's bottom-right, 8 px inset. */
98
+ .hs-card__play {
99
+ position: absolute;
100
+ right: 8px;
101
+ bottom: 8px;
102
+ z-index: 2;
103
+ opacity: 0;
104
+ transform: translateY(4px);
105
+ box-shadow: 0 2px 8px rgb(0 0 0 / 25%);
106
+ transition: opacity var(--hs-duration-hover) var(--hs-ease),
107
+ transform var(--hs-duration-hover) var(--hs-ease);
108
+ }
109
+
110
+ .hs-card:hover,
111
+ .hs-card:active {
112
+ background: var(--hs-control-tone);
113
+ }
114
+
115
+ .hs-card:hover .hs-card__play,
116
+ .hs-card:focus-within .hs-card__play {
117
+ opacity: 1;
118
+ transform: none;
119
+ }
120
+
121
+ .hs-card:active .hs-card__cover {
122
+ transform: scale(0.98);
123
+ }
124
+
125
+ .hs-card:has(.hs-card__link:focus-visible) .hs-card__cover {
126
+ transform: translateY(-2px) scale(1.03);
127
+ box-shadow: var(--hs-focus-shadow);
128
+ }
129
+
130
+ .hs-card:has(.hs-card__link:focus-visible) .hs-card__title {
131
+ color: var(--hs-accent-text);
132
+ }
133
+
134
+ /* k14 B - round picture, name under, centred, 4 px disc inset. */
135
+ .hs-card--artist .hs-card__cover {
136
+ border-radius: 50%;
137
+ }
138
+
139
+ .hs-card--artist .hs-art-placeholder .hs-icon {
140
+ --hs-icon-size: 40%;
141
+ }
142
+
143
+ .hs-card--artist .hs-card__play {
144
+ right: 4px;
145
+ bottom: 4px;
146
+ }
147
+
148
+ .hs-card--artist .hs-card__text {
149
+ align-items: center;
150
+ text-align: center;
151
+ }
152
+
153
+ /* f09 - art corners drop to 6 px below a 120 px cover. */
154
+ @container (max-width: 119px) {
155
+ .hs-card__cover {
156
+ border-radius: var(--hs-radius-art-small);
157
+ }
158
+
159
+ .hs-card__cover > .hs-mosaic {
160
+ border-radius: var(--hs-radius-art-small);
161
+ }
162
+ }
163
+
164
+ @media (prefers-reduced-motion: reduce) {
165
+ .hs-card,
166
+ .hs-card__cover,
167
+ .hs-card__play {
168
+ transition: none;
169
+ }
170
+ }
171
+
172
+ /* ------------------------------------------------------------------ */
173
+ /* k16 C - playlist mosaic cover */
174
+ /* ------------------------------------------------------------------ */
175
+
176
+ .hs-mosaic {
177
+ width: 100%;
178
+ height: 100%;
179
+ display: grid;
180
+ border-radius: inherit;
181
+ overflow: hidden;
182
+ }
183
+
184
+ .hs-mosaic img {
185
+ width: 100%;
186
+ height: 100%;
187
+ min-height: 0;
188
+ display: block;
189
+ object-fit: cover;
190
+ }
191
+
192
+ .hs-mosaic .hs-art-placeholder {
193
+ border-radius: 0;
194
+ min-height: 0;
195
+ }
196
+
197
+ .hs-mosaic--1 {
198
+ grid-template: 1fr / 1fr;
199
+ }
200
+
201
+ .hs-mosaic--2 {
202
+ grid-template: 1fr / 1fr 1fr;
203
+ }
204
+
205
+ .hs-mosaic--3 {
206
+ grid-template: 1fr 1fr / 1fr 1fr;
207
+ }
208
+
209
+ .hs-mosaic--3 > :first-child {
210
+ grid-row: 1 / 3;
211
+ }
212
+
213
+ .hs-mosaic--4 {
214
+ grid-template: 1fr 1fr / 1fr 1fr;
215
+ }
216
+
217
+ /* ------------------------------------------------------------------ */
218
+ /* l10 - admin Overview cards */
219
+ /* ------------------------------------------------------------------ */
220
+
221
+ .hs-admin-card {
222
+ background: var(--hs-group-bg);
223
+ box-shadow: var(--hs-group-shadow);
224
+ border-radius: var(--hs-radius-card);
225
+ padding: 16px;
226
+ display: flex;
227
+ flex-direction: column;
228
+ gap: 10px;
229
+ align-items: flex-start;
230
+ color: var(--hs-fg);
231
+ text-decoration: none;
232
+ }
233
+
234
+ .hs-admin-card__header {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 8px;
238
+ width: 100%;
239
+ font-weight: 600;
240
+ }
241
+
242
+ .hs-admin-card__header .hs-icon {
243
+ width: 16px;
244
+ height: 16px;
245
+ color: var(--hs-fg-muted);
246
+ }
247
+
248
+ .hs-admin-card__header .hs-icon:last-child {
249
+ margin-left: auto;
250
+ }
251
+
252
+ .hs-admin-card__number {
253
+ font: 750 29px var(--hs-font-display);
254
+ letter-spacing: -0.02em;
255
+ }
256
+
257
+ /* c04 value line under the key number. */
258
+ .hs-admin-card__line {
259
+ color: var(--hs-fg-muted);
260
+ font-size: 13px;
261
+ }
262
+
263
+ .hs-admin-card .hs-progress {
264
+ width: 100%;
265
+ }
266
+
267
+ .hs-admin-card:focus-visible {
268
+ outline: none;
269
+ background: var(--hs-accent-tint);
270
+ box-shadow: var(--hs-focus-shadow);
271
+ }
272
+
273
+ /* ------------------------------------------------------------------ */
274
+ /* p18 - Top Result card */
275
+ /* ------------------------------------------------------------------ */
276
+
277
+ .hs-top-result-row {
278
+ display: grid;
279
+ grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
280
+ gap: 24px;
281
+ padding: 0 24px 8px 32px;
282
+ }
283
+
284
+ .hs-top-result {
285
+ position: relative;
286
+ background: var(--hs-group-bg);
287
+ border-radius: var(--hs-radius-card);
288
+ padding: 18px;
289
+ display: flex;
290
+ flex-direction: column;
291
+ gap: 6px;
292
+ align-items: flex-start;
293
+ }
294
+
295
+ .hs-top-result__art {
296
+ width: 96px;
297
+ height: 96px;
298
+ border-radius: var(--hs-radius-art);
299
+ overflow: hidden;
300
+ display: block;
301
+ margin-bottom: 8px;
302
+ box-shadow: var(--hs-art-shadow);
303
+ }
304
+
305
+ .hs-top-result__art img {
306
+ width: 100%;
307
+ height: 100%;
308
+ display: block;
309
+ object-fit: cover;
310
+ }
311
+
312
+ .hs-top-result__name {
313
+ font: 750 26px/1.15 var(--hs-font-display);
314
+ letter-spacing: -0.02em;
315
+ }
316
+
317
+ .hs-top-result__meta {
318
+ color: var(--hs-fg-muted);
319
+ font-size: 13px;
320
+ }
321
+
322
+ .hs-top-result .hs-play-button {
323
+ position: absolute;
324
+ right: 18px;
325
+ bottom: 18px;
326
+ }
327
+
328
+ @media (max-width: 1000px) {
329
+ .hs-top-result-row {
330
+ grid-template-columns: 1fr;
331
+ padding: 0 24px;
332
+ }
333
+ }
334
+
335
+ @media (max-width: 720px) {
336
+ .hs-top-result-row {
337
+ padding: 0 14px;
338
+ }
339
+ }
@@ -0,0 +1,202 @@
1
+ /*
2
+ * k06 checkbox and radio (k06 C: outline at rest, bright accent when on) and
3
+ * k07-r2 switch (light: white shadowed knob; dark: dark knob on yellow).
4
+ *
5
+ * Markup: <label class="hs-choice"><input type="checkbox" class="hs-choice__input">
6
+ * <span class="hs-choice__box"><svg class="hs-icon hs-choice__check">...</svg></span>Label
7
+ * </label>. The native input is the control; the box is its face. A radio row adds
8
+ * .hs-choice--radio and an 8 px .hs-choice__dot instead of the check; an on box adds
9
+ * .hs-choice__box--on.
10
+ *
11
+ * ACCEPTED EXCEPTION (k07-r2, foundations.md 12.1 item 1): the light on state of the
12
+ * switch has no 3:1 pair.
13
+ */
14
+
15
+ /* ------------------------------------------------------------------ */
16
+ /* k06 - checkbox and radio */
17
+ /* ------------------------------------------------------------------ */
18
+
19
+ .hs-choice {
20
+ position: relative;
21
+ display: inline-flex;
22
+ align-items: center;
23
+ gap: 10px;
24
+ min-height: 32px;
25
+ padding: 0 10px 0 6px;
26
+ border-radius: var(--hs-radius-control);
27
+ font: 14px var(--hs-font-body);
28
+ color: var(--hs-fg);
29
+ cursor: default;
30
+ user-select: none;
31
+ transition:
32
+ background var(--hs-duration-hover) var(--hs-ease),
33
+ color var(--hs-duration-hover) var(--hs-ease);
34
+ }
35
+
36
+ /* The native control keeps its semantics and keyboard behaviour; the box draws it. */
37
+ .hs-choice__input {
38
+ position: absolute;
39
+ width: 1px;
40
+ height: 1px;
41
+ margin: 0;
42
+ opacity: 0;
43
+ pointer-events: none;
44
+ }
45
+
46
+ .hs-choice__box {
47
+ display: inline-flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ flex: none;
51
+ width: 20px;
52
+ height: 20px;
53
+ box-sizing: border-box;
54
+ border-radius: 6px;
55
+ box-shadow: inset 0 0 0 2px var(--hs-fg-muted);
56
+ transition:
57
+ background var(--hs-duration-hover) var(--hs-ease),
58
+ box-shadow var(--hs-duration-hover) var(--hs-ease);
59
+ }
60
+
61
+ .hs-choice--radio .hs-choice__box {
62
+ border-radius: 50%;
63
+ }
64
+
65
+ /* The check mark is drawn by the box, so it only shows when on. Mixed uses the same slot
66
+ * with adwaita/remove (k06). */
67
+ .hs-choice__check {
68
+ --hs-icon-size: 14px;
69
+ display: none;
70
+ }
71
+
72
+ .hs-choice__box .hs-choice__dot {
73
+ display: none;
74
+ }
75
+
76
+ .hs-choice__box--on {
77
+ box-shadow: none;
78
+ background: var(--hs-accent-bg);
79
+ color: var(--hs-accent-fg);
80
+ }
81
+
82
+ .hs-choice__box--on .hs-choice__check {
83
+ display: inline-block;
84
+ }
85
+
86
+ .hs-choice__dot {
87
+ width: 8px;
88
+ height: 8px;
89
+ border-radius: 50%;
90
+ background: var(--hs-accent-fg);
91
+ }
92
+
93
+ .hs-choice__box--on .hs-choice__dot {
94
+ display: block;
95
+ }
96
+
97
+ .hs-choice:hover .hs-choice__box:not(.hs-choice__box--on) {
98
+ box-shadow: inset 0 0 0 2px var(--hs-fg);
99
+ background: var(--hs-control-tone);
100
+ }
101
+
102
+ .hs-choice:active .hs-choice__box:not(.hs-choice__box--on) {
103
+ box-shadow: inset 0 0 0 2px var(--hs-fg);
104
+ background: color-mix(in srgb, var(--hs-fg) 18%, transparent);
105
+ }
106
+
107
+ .hs-choice:hover .hs-choice__box--on {
108
+ background: color-mix(in srgb, var(--hs-accent-bg) 90%, #000);
109
+ }
110
+
111
+ .hs-choice:active .hs-choice__box--on {
112
+ background: color-mix(in srgb, var(--hs-accent-bg) 80%, #000);
113
+ }
114
+
115
+ /* f13-r3: the row takes the tint, the label the accent colour at weight 600. */
116
+ .hs-choice:focus-visible,
117
+ .hs-choice:has(.hs-choice__input:focus-visible),
118
+ .hs-choice:has(.hs-switch:focus-visible) {
119
+ outline: none;
120
+ background: var(--hs-accent-tint);
121
+ color: var(--hs-accent-text);
122
+ font-weight: 600;
123
+ box-shadow: var(--hs-focus-shadow);
124
+ }
125
+
126
+ .hs-choice--disabled,
127
+ .hs-choice[aria-disabled='true'],
128
+ .hs-choice:has(.hs-choice__input:disabled),
129
+ .hs-choice:has(.hs-switch:disabled) {
130
+ opacity: 0.4;
131
+ pointer-events: none;
132
+ }
133
+
134
+ /* ------------------------------------------------------------------ */
135
+ /* k07-r2 - switch */
136
+ /* ------------------------------------------------------------------ */
137
+
138
+ .hs-switch {
139
+ position: relative;
140
+ display: inline-block;
141
+ flex: none;
142
+ width: 44px;
143
+ height: 24px;
144
+ box-sizing: border-box;
145
+ margin: 0;
146
+ padding: 0;
147
+ border: 0;
148
+ border-radius: 12px;
149
+ background: var(--hs-switch-off);
150
+ cursor: default;
151
+ appearance: none;
152
+ transition: background var(--hs-duration-hover) var(--hs-ease);
153
+ }
154
+
155
+ .hs-switch::after {
156
+ content: '';
157
+ position: absolute;
158
+ top: 3px;
159
+ left: 3px;
160
+ width: 18px;
161
+ height: 18px;
162
+ border-radius: 9px;
163
+ background: var(--hs-switch-knob);
164
+ box-shadow: var(--hs-switch-knob-shadow);
165
+ transition:
166
+ left var(--hs-duration-press) var(--hs-ease),
167
+ width var(--hs-duration-press) var(--hs-ease),
168
+ background var(--hs-duration-hover) var(--hs-ease);
169
+ }
170
+
171
+ .hs-switch--on,
172
+ .hs-switch[aria-checked='true'] {
173
+ background: var(--hs-accent-bg);
174
+ }
175
+
176
+ .hs-switch--on::after,
177
+ .hs-switch[aria-checked='true']::after {
178
+ left: 23px;
179
+ background: var(--hs-switch-knob-on);
180
+ }
181
+
182
+ /* The switch lives in a k11-r1 row, so hover and press come from the row. */
183
+ .hs-choice:hover .hs-switch:not(.hs-switch--on):not([aria-checked='true']) {
184
+ background: color-mix(in srgb, var(--hs-fg) 62%, var(--hs-view-bg));
185
+ }
186
+
187
+ .hs-choice:hover .hs-switch--on,
188
+ .hs-choice:hover .hs-switch[aria-checked='true'],
189
+ .hs-choice:active .hs-switch--on,
190
+ .hs-choice:active .hs-switch[aria-checked='true'] {
191
+ background: color-mix(in srgb, var(--hs-accent-bg) 90%, #000);
192
+ }
193
+
194
+ /* Press: the knob stretches to 22 px; the on knob's left position follows. */
195
+ .hs-choice:active .hs-switch::after {
196
+ width: 22px;
197
+ }
198
+
199
+ .hs-choice:active .hs-switch--on::after,
200
+ .hs-choice:active .hs-switch[aria-checked='true']::after {
201
+ left: 19px;
202
+ }
@@ -0,0 +1,85 @@
1
+ /*
2
+ * k19 C - dialogs: a centred card on desktop, a bottom card on phones (l11c A), the
3
+ * 640 px instance-dialog exception (p05-r1 A) and the o05 A no-close-button rule.
4
+ *
5
+ * Markup: <div class="hs-scrim"></div> then <div class="hs-dialog" role="dialog"
6
+ * aria-modal="true" aria-labelledby="...">. Alerts use role="alertdialog" with
7
+ * aria-describedby on the alert text and a destructive action button; action dialogs
8
+ * carry the suggested button. There is never a close button: Escape, a click on the
9
+ * scrim or Cancel closes the dialog. Focus moves in and is trapped by the page.
10
+ * Long forms grow in height and scroll inside (l11c).
11
+ */
12
+
13
+ /* p17 z-index fix: above the sticky page header (5), below the dialog (10). */
14
+ .hs-scrim {
15
+ position: fixed;
16
+ inset: 0;
17
+ z-index: 9;
18
+ background: rgb(0 0 0 / 40%);
19
+ }
20
+
21
+ .hs-dialog {
22
+ position: fixed;
23
+ z-index: 10;
24
+ left: 50%;
25
+ top: 50%;
26
+ transform: translate(-50%, -50%);
27
+ width: min(340px, calc(100vw - 48px));
28
+ max-height: calc(100vh - 48px);
29
+ overflow: auto;
30
+ box-sizing: border-box;
31
+ padding: 22px;
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 14px;
35
+ background: var(--hs-dialog-bg);
36
+ border-radius: var(--hs-radius-dialog);
37
+ box-shadow: var(--hs-elevation-3);
38
+ color: var(--hs-fg);
39
+ font: 400 14px/1.45 var(--hs-font-body);
40
+ }
41
+
42
+ /* p05-r1 A: the instance dialog (setup Configure and admin Instances) is 640 px wide. */
43
+ .hs-dialog--wide {
44
+ width: min(640px, calc(100vw - 48px));
45
+ }
46
+
47
+ .hs-dialog__title {
48
+ margin: 0;
49
+ font: 750 19px/1.2 var(--hs-font-display);
50
+ letter-spacing: -0.02em;
51
+ }
52
+
53
+ .hs-dialog__footer {
54
+ display: flex;
55
+ justify-content: flex-end;
56
+ gap: 8px;
57
+ }
58
+
59
+ /* Alerts are the same card: role="alertdialog" with aria-describedby on the alert text
60
+ * and a destructive action button; action dialogs use the suggested button (k19). */
61
+
62
+ /* ------------------------------------------------------------------ */
63
+ /* Phone (l07): bottom card, stacked full-width buttons */
64
+ /* ------------------------------------------------------------------ */
65
+
66
+ @media (max-width: 720px) {
67
+ .hs-dialog {
68
+ left: 10px;
69
+ right: 10px;
70
+ bottom: 10px;
71
+ top: auto;
72
+ width: auto;
73
+ max-height: calc(100vh - 20px);
74
+ transform: none;
75
+ }
76
+
77
+ .hs-dialog__footer {
78
+ flex-direction: column-reverse;
79
+ }
80
+
81
+ .hs-dialog__footer .hs-button {
82
+ width: 100%;
83
+ height: 44px;
84
+ }
85
+ }