@hearthsound/design 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +132 -2
- package/THIRD-PARTY.md +46 -0
- package/css/base.css +245 -0
- package/css/components/admin.css +257 -0
- package/css/components/banner.css +140 -0
- package/css/components/button.css +309 -0
- package/css/components/card.css +339 -0
- package/css/components/check.css +202 -0
- package/css/components/dialog.css +85 -0
- package/css/components/field.css +296 -0
- package/css/components/list.css +260 -0
- package/css/components/menu.css +282 -0
- package/css/components/page-header.css +230 -0
- package/css/components/pill.css +101 -0
- package/css/components/player.css +524 -0
- package/css/components/progress.css +173 -0
- package/css/components/section.css +86 -0
- package/css/components/segmented.css +64 -0
- package/css/components/shell.css +281 -0
- package/css/components/sidebar.css +170 -0
- package/css/components/slider.css +92 -0
- package/css/components/status-page.css +48 -0
- package/css/components/stepper.css +130 -0
- package/css/components/toast.css +88 -0
- package/css/components/tooltip.css +29 -0
- package/css/components/track.css +336 -0
- package/css/components/upload.css +70 -0
- package/css/index.css +35 -0
- package/css/tokens.css +375 -0
- package/dist/icons.d.ts +56 -0
- package/dist/icons.js +56 -0
- package/dist/icons.svg +55 -0
- package/fonts/OFL-BricolageGrotesque.txt +93 -0
- package/fonts/OFL-Geist.txt +92 -0
- package/fonts/bricolage-var.woff2 +0 -0
- package/fonts/geist-mono.woff2 +0 -0
- package/fonts/geist-var.woff2 +0 -0
- package/icons/LICENSE +10 -0
- package/icons/adwaita-account.svg +1 -0
- package/icons/adwaita-acquire.svg +1 -0
- package/icons/adwaita-add.svg +1 -0
- package/icons/adwaita-album.svg +1 -0
- package/icons/adwaita-artist.svg +1 -0
- package/icons/adwaita-back.svg +1 -0
- package/icons/adwaita-check.svg +1 -0
- package/icons/adwaita-close.svg +1 -0
- package/icons/adwaita-collapse.svg +1 -0
- package/icons/adwaita-dark-mode.svg +1 -0
- package/icons/adwaita-delete.svg +1 -0
- package/icons/adwaita-drag.svg +1 -0
- package/icons/adwaita-edit.svg +1 -0
- package/icons/adwaita-error.svg +1 -0
- package/icons/adwaita-expand.svg +1 -0
- package/icons/adwaita-folder.svg +1 -0
- package/icons/adwaita-forward.svg +1 -0
- package/icons/adwaita-home.svg +1 -0
- package/icons/adwaita-layers.svg +1 -0
- package/icons/adwaita-like.svg +1 -0
- package/icons/adwaita-lock.svg +1 -0
- package/icons/adwaita-menu.svg +1 -0
- package/icons/adwaita-more.svg +1 -0
- package/icons/adwaita-mute.svg +1 -0
- package/icons/adwaita-next.svg +1 -0
- package/icons/adwaita-pause.svg +1 -0
- package/icons/adwaita-play.svg +1 -0
- package/icons/adwaita-playlist.svg +1 -0
- package/icons/adwaita-plugin.svg +1 -0
- package/icons/adwaita-previous.svg +1 -0
- package/icons/adwaita-queue.svg +1 -0
- package/icons/adwaita-rating-outline.svg +1 -0
- package/icons/adwaita-rating.svg +1 -0
- package/icons/adwaita-refresh.svg +1 -0
- package/icons/adwaita-remote.svg +1 -0
- package/icons/adwaita-remove.svg +1 -0
- package/icons/adwaita-repeat.svg +1 -0
- package/icons/adwaita-reveal.svg +1 -0
- package/icons/adwaita-search.svg +1 -0
- package/icons/adwaita-settings.svg +1 -0
- package/icons/adwaita-shuffle.svg +1 -0
- package/icons/adwaita-sign-out.svg +1 -0
- package/icons/adwaita-song.svg +1 -0
- package/icons/adwaita-sort.svg +1 -0
- package/icons/adwaita-storage.svg +1 -0
- package/icons/adwaita-users.svg +1 -0
- package/icons/adwaita-volume.svg +1 -0
- package/icons/adwaita-warning.svg +1 -0
- package/icons/custom-dislike-outline.svg +1 -0
- package/icons/custom-dislike.svg +1 -0
- package/icons/custom-like-outline.svg +1 -0
- package/icons/custom-unknown.svg +1 -0
- package/icons/custom-upload.svg +1 -0
- package/identity/icons/app-icon-dark-16.png +0 -0
- package/identity/icons/app-icon-dark-180.png +0 -0
- package/identity/icons/app-icon-dark-192.png +0 -0
- package/identity/icons/app-icon-dark-32.png +0 -0
- package/identity/icons/app-icon-dark-512.png +0 -0
- package/identity/icons/app-icon-dark.svg +1 -0
- package/identity/icons/app-icon-light-16.png +0 -0
- package/identity/icons/app-icon-light-180.png +0 -0
- package/identity/icons/app-icon-light-192.png +0 -0
- package/identity/icons/app-icon-light-32.png +0 -0
- package/identity/icons/app-icon-light-512.png +0 -0
- package/identity/icons/app-icon-light.svg +1 -0
- package/identity/icons/favicon.svg +1 -0
- package/identity/mark/mark-dark.svg +1 -0
- package/identity/mark/mark-light.svg +1 -0
- package/identity/mark/mark-symbolic.svg +1 -0
- package/package.json +35 -4
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* k35 A - the player bar and the phone mini player (l04 B, l07 C), the o02 idle state,
|
|
3
|
+
* the p19-r1 fetch states ("Failed" pill anchored for the k27 tooltip, retry disc) and
|
|
4
|
+
* the p20-r4 now-playing view parts (p19-r1 queue, p20b unsynced lyrics, c03 item 12
|
|
5
|
+
* source line).
|
|
6
|
+
*
|
|
7
|
+
* The bar is a grid area under the content column in the shell. The mini player is the
|
|
8
|
+
* phone replacement and keeps its 8 px inset from the window edges.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* ------------------------------------------------------------------ */
|
|
12
|
+
/* k35 - player bar */
|
|
13
|
+
/* ------------------------------------------------------------------ */
|
|
14
|
+
|
|
15
|
+
.hs-player {
|
|
16
|
+
display: grid;
|
|
17
|
+
grid-template-columns: 1fr minmax(360px, 1.4fr) 1fr;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 16px;
|
|
20
|
+
height: 88px;
|
|
21
|
+
padding: 0 18px;
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
background: var(--hs-headerbar-bg);
|
|
24
|
+
box-shadow: 0 -1px 0 var(--hs-separator);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Left zone: cover, title over artist; both lines truncate. */
|
|
28
|
+
.hs-player__now-playing {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
gap: 12px;
|
|
32
|
+
min-width: 0;
|
|
33
|
+
padding: 0;
|
|
34
|
+
margin: 0;
|
|
35
|
+
border: 0;
|
|
36
|
+
border-radius: var(--hs-radius-row);
|
|
37
|
+
background: transparent;
|
|
38
|
+
color: inherit;
|
|
39
|
+
font: inherit;
|
|
40
|
+
text-align: left;
|
|
41
|
+
appearance: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* f13-r3: the song region is the first tab stop and opens the now-playing view. */
|
|
45
|
+
.hs-player__now-playing:focus-visible {
|
|
46
|
+
outline: none;
|
|
47
|
+
background: var(--hs-accent-tint);
|
|
48
|
+
color: var(--hs-accent-text);
|
|
49
|
+
box-shadow: var(--hs-focus-shadow);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.hs-player__cover {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: center;
|
|
56
|
+
flex: none;
|
|
57
|
+
width: 52px;
|
|
58
|
+
height: 52px;
|
|
59
|
+
border-radius: var(--hs-radius-art-small);
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
background: var(--hs-control-tone);
|
|
62
|
+
color: var(--hs-fg-muted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.hs-player__cover > img {
|
|
66
|
+
display: block;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* o02: the idle art slot is a control-tone tile with a 22 px muted song glyph. */
|
|
72
|
+
.hs-player__cover > .hs-icon {
|
|
73
|
+
--hs-icon-size: 22px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.hs-player__meta {
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
gap: 2px;
|
|
80
|
+
min-width: 0;
|
|
81
|
+
position: relative; /* the k27 tooltip of a Failed pill anchors here */
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.hs-player__title-row {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
min-width: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hs-player__title {
|
|
92
|
+
min-width: 0;
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
text-overflow: ellipsis;
|
|
95
|
+
white-space: nowrap;
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.hs-player__artist {
|
|
100
|
+
overflow: hidden;
|
|
101
|
+
text-overflow: ellipsis;
|
|
102
|
+
white-space: nowrap;
|
|
103
|
+
font-size: 13px;
|
|
104
|
+
color: var(--hs-fg-muted);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Centre zone: the transport row above the seek row with times at either side. */
|
|
108
|
+
.hs-player__transport {
|
|
109
|
+
display: flex;
|
|
110
|
+
flex-direction: column;
|
|
111
|
+
align-items: center;
|
|
112
|
+
gap: 4px;
|
|
113
|
+
min-width: 0;
|
|
114
|
+
width: 100%;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.hs-player__seek-row {
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 10px;
|
|
121
|
+
width: 100%;
|
|
122
|
+
font: 400 12px var(--hs-font-body);
|
|
123
|
+
font-variant-numeric: tabular-nums;
|
|
124
|
+
color: var(--hs-fg-muted);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.hs-player__times {
|
|
128
|
+
flex: none;
|
|
129
|
+
font-variant-numeric: tabular-nums;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Right zone: mute, the 150 px volume slider and the queue toggle. */
|
|
133
|
+
.hs-player__end {
|
|
134
|
+
display: flex;
|
|
135
|
+
align-items: center;
|
|
136
|
+
justify-content: flex-end;
|
|
137
|
+
gap: 6px;
|
|
138
|
+
min-width: 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.hs-player__volume {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 4px;
|
|
145
|
+
width: 150px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* o02 - idle: muted title; the controls carry aria-disabled and their own 40% faded
|
|
149
|
+
* look (k01d), the fills are empty and the artist line is absent. */
|
|
150
|
+
|
|
151
|
+
.hs-player--idle .hs-player__title {
|
|
152
|
+
color: var(--hs-fg-muted);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ------------------------------------------------------------------ */
|
|
156
|
+
/* l07 C - fold at 721-1000 px */
|
|
157
|
+
/* ------------------------------------------------------------------ */
|
|
158
|
+
|
|
159
|
+
@media (min-width: 721px) and (max-width: 1000px) {
|
|
160
|
+
.hs-player {
|
|
161
|
+
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
162
|
+
gap: 12px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.hs-player__transport {
|
|
166
|
+
min-width: 220px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Shuffle and repeat are the first and last transport buttons. */
|
|
170
|
+
.hs-player .hs-transport > :first-child,
|
|
171
|
+
.hs-player .hs-transport > :last-child {
|
|
172
|
+
display: none;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.hs-player__volume {
|
|
176
|
+
width: auto;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.hs-player__volume .hs-slider {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* l01-r1, l04 B: the bar is replaced by the mini player card on phones. */
|
|
185
|
+
@media (max-width: 720px) {
|
|
186
|
+
.hs-player:not(.hs-player--mini) {
|
|
187
|
+
display: none;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* ------------------------------------------------------------------ */
|
|
192
|
+
/* k35 A - phone mini player (l04 B) */
|
|
193
|
+
/* ------------------------------------------------------------------ */
|
|
194
|
+
|
|
195
|
+
.hs-player--mini {
|
|
196
|
+
position: relative;
|
|
197
|
+
display: flex;
|
|
198
|
+
align-items: center;
|
|
199
|
+
gap: 12px;
|
|
200
|
+
height: 64px;
|
|
201
|
+
margin: 0 8px 8px;
|
|
202
|
+
padding: 0 10px 0 8px;
|
|
203
|
+
box-sizing: border-box;
|
|
204
|
+
overflow: hidden;
|
|
205
|
+
border-radius: 14px;
|
|
206
|
+
background: var(--hs-group-bg);
|
|
207
|
+
box-shadow: var(--hs-group-shadow);
|
|
208
|
+
color: var(--hs-fg);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.hs-player--mini .hs-player__cover {
|
|
212
|
+
width: 48px;
|
|
213
|
+
height: 48px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.hs-player--mini .hs-player__meta {
|
|
217
|
+
flex: 1;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.hs-player--mini .hs-player__progress-line {
|
|
221
|
+
position: absolute;
|
|
222
|
+
left: 0;
|
|
223
|
+
right: 0;
|
|
224
|
+
bottom: 0;
|
|
225
|
+
height: 3px;
|
|
226
|
+
background: color-mix(in srgb, var(--hs-fg) 16%, transparent);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.hs-player--mini:focus-visible {
|
|
230
|
+
outline: none;
|
|
231
|
+
box-shadow: var(--hs-focus-shadow);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.hs-player__progress-line > i {
|
|
235
|
+
position: absolute;
|
|
236
|
+
left: 0;
|
|
237
|
+
top: 0;
|
|
238
|
+
bottom: 0;
|
|
239
|
+
background: var(--hs-accent-bg);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* o02: nothing playing hides the progress line and the artist line is absent. */
|
|
243
|
+
.hs-player--mini.hs-player--idle .hs-player__progress-line {
|
|
244
|
+
display: none;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* ------------------------------------------------------------------ */
|
|
248
|
+
/* p20-r4 - now-playing view */
|
|
249
|
+
/* ------------------------------------------------------------------ */
|
|
250
|
+
|
|
251
|
+
.hs-now-playing {
|
|
252
|
+
position: fixed;
|
|
253
|
+
inset: 0;
|
|
254
|
+
z-index: 40;
|
|
255
|
+
display: grid;
|
|
256
|
+
grid-template-columns: min(400px, 44vh) 460px;
|
|
257
|
+
justify-content: center;
|
|
258
|
+
align-items: center;
|
|
259
|
+
gap: 80px;
|
|
260
|
+
padding: 48px 56px;
|
|
261
|
+
box-sizing: border-box;
|
|
262
|
+
overflow: auto;
|
|
263
|
+
background: var(--hs-view-bg);
|
|
264
|
+
color: var(--hs-fg);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* The left column is as wide as the cover. Rows under the cover span that width. */
|
|
268
|
+
.hs-now-playing__left {
|
|
269
|
+
display: grid;
|
|
270
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
271
|
+
grid-template-areas:
|
|
272
|
+
'cover cover'
|
|
273
|
+
'details actions'
|
|
274
|
+
'seek seek'
|
|
275
|
+
'transport transport';
|
|
276
|
+
align-items: start;
|
|
277
|
+
gap: 16px;
|
|
278
|
+
min-width: 0;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.hs-now-playing__cover {
|
|
282
|
+
grid-area: cover;
|
|
283
|
+
display: block;
|
|
284
|
+
width: 100%;
|
|
285
|
+
aspect-ratio: 1;
|
|
286
|
+
border-radius: var(--hs-radius-art);
|
|
287
|
+
overflow: hidden;
|
|
288
|
+
background: var(--hs-art-placeholder-bg);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.hs-now-playing__cover > img {
|
|
292
|
+
display: block;
|
|
293
|
+
width: 100%;
|
|
294
|
+
height: 100%;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.hs-now-playing__details {
|
|
298
|
+
grid-area: details;
|
|
299
|
+
display: flex;
|
|
300
|
+
flex-direction: column;
|
|
301
|
+
gap: 4px;
|
|
302
|
+
min-width: 0;
|
|
303
|
+
position: relative;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.hs-now-playing__title {
|
|
307
|
+
margin: 0;
|
|
308
|
+
font: 750 26px/1.15 var(--hs-font-display);
|
|
309
|
+
letter-spacing: -0.02em;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.hs-now-playing__artist {
|
|
313
|
+
margin: 0;
|
|
314
|
+
font-size: 15px;
|
|
315
|
+
color: var(--hs-fg-muted);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.hs-now-playing__actions {
|
|
319
|
+
grid-area: actions;
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: 2px;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* k17-r3: a pressed like or dislike stays transparent with the accent glyph. */
|
|
326
|
+
.hs-now-playing__actions .hs-button--on,
|
|
327
|
+
.hs-now-playing__actions .hs-button[aria-pressed='true'] {
|
|
328
|
+
background: transparent;
|
|
329
|
+
color: var(--hs-accent-text);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.hs-now-playing__seek {
|
|
333
|
+
grid-area: seek;
|
|
334
|
+
display: flex;
|
|
335
|
+
align-items: center;
|
|
336
|
+
gap: 10px;
|
|
337
|
+
width: 100%;
|
|
338
|
+
font: 400 12px var(--hs-font-body);
|
|
339
|
+
font-variant-numeric: tabular-nums;
|
|
340
|
+
color: var(--hs-fg-muted);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.hs-now-playing__transport {
|
|
344
|
+
grid-area: transport;
|
|
345
|
+
display: flex;
|
|
346
|
+
align-items: center;
|
|
347
|
+
justify-content: space-between;
|
|
348
|
+
gap: 14px;
|
|
349
|
+
width: 100%;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.hs-now-playing__close {
|
|
353
|
+
position: absolute;
|
|
354
|
+
left: 24px;
|
|
355
|
+
top: 20px;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/* Right column: the text switch and one panel of the same width. */
|
|
359
|
+
.hs-now-playing__right {
|
|
360
|
+
display: flex;
|
|
361
|
+
flex-direction: column;
|
|
362
|
+
gap: 14px;
|
|
363
|
+
width: 100%;
|
|
364
|
+
height: min(640px, calc(100vh - 96px));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.hs-now-playing__switch {
|
|
368
|
+
align-self: flex-start;
|
|
369
|
+
margin: 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.hs-now-playing__panel {
|
|
373
|
+
flex: 1;
|
|
374
|
+
min-height: 0;
|
|
375
|
+
position: relative;
|
|
376
|
+
overflow: auto;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* Lyrics, synced (p20-r4): the current line is held at the panel's vertical centre. */
|
|
380
|
+
.hs-lyrics {
|
|
381
|
+
display: flex;
|
|
382
|
+
flex-direction: column;
|
|
383
|
+
gap: 12px;
|
|
384
|
+
padding: 50vh 4px;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.hs-lyrics-line {
|
|
388
|
+
margin: 0;
|
|
389
|
+
font: 700 30px/1.3 var(--hs-font-display);
|
|
390
|
+
letter-spacing: -0.01em;
|
|
391
|
+
color: color-mix(in srgb, var(--hs-fg) 38%, transparent);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.hs-lyrics-line[aria-current='true'] {
|
|
395
|
+
color: var(--hs-fg);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.hs-lyrics-note {
|
|
399
|
+
font-size: 13px;
|
|
400
|
+
color: var(--hs-fg-muted);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* p20b: unsynced lyrics scroll by hand from the top, nothing is highlighted. */
|
|
404
|
+
.hs-lyrics--unsynced {
|
|
405
|
+
padding: 4px 4px 24px;
|
|
406
|
+
gap: 18px;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.hs-lyrics--unsynced .hs-lyrics-line {
|
|
410
|
+
font: 500 19px/1.55 var(--hs-font-body);
|
|
411
|
+
letter-spacing: 0;
|
|
412
|
+
color: var(--hs-fg);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.hs-lyrics--unsynced .hs-lyrics-note {
|
|
416
|
+
display: flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
gap: 6px;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* c03 item 12: every lyrics panel ends with the source line. */
|
|
422
|
+
.hs-lyrics-note--source {
|
|
423
|
+
margin-top: 10px;
|
|
424
|
+
font-size: 12px;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Queue (p19-r1): cover, title/artist and the pill + duration end cell. */
|
|
428
|
+
.hs-now-playing__panel .hs-track-list {
|
|
429
|
+
grid-template-columns: 40px minmax(0, 1fr) auto;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.hs-now-playing__panel .hs-track-row--queue {
|
|
433
|
+
grid-template-columns: subgrid;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.hs-now-playing__panel .hs-track-row--queue .hs-track-row__actions {
|
|
437
|
+
display: none;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.hs-now-playing__queue-end {
|
|
441
|
+
display: flex;
|
|
442
|
+
align-items: center;
|
|
443
|
+
justify-content: flex-end;
|
|
444
|
+
gap: 10px;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.hs-now-playing__queue-end .hs-track-row__duration {
|
|
448
|
+
width: 44px;
|
|
449
|
+
text-align: right;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* ------------------------------------------------------------------ */
|
|
453
|
+
/* l07 - middle widths (p20-r4: 1001-1100 px) */
|
|
454
|
+
/* ------------------------------------------------------------------ */
|
|
455
|
+
|
|
456
|
+
@media (max-width: 1100px) {
|
|
457
|
+
.hs-now-playing {
|
|
458
|
+
grid-template-columns: min(340px, 40vh) 400px;
|
|
459
|
+
gap: 48px;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.hs-lyrics-line {
|
|
463
|
+
font-size: 26px;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* ------------------------------------------------------------------ */
|
|
468
|
+
/* Phone (p20-r4 6.6): one scrolled column, 320 px lyrics panel */
|
|
469
|
+
/* ------------------------------------------------------------------ */
|
|
470
|
+
|
|
471
|
+
@media (max-width: 720px) {
|
|
472
|
+
.hs-now-playing {
|
|
473
|
+
display: flex;
|
|
474
|
+
flex-direction: column;
|
|
475
|
+
align-items: stretch;
|
|
476
|
+
justify-content: flex-start;
|
|
477
|
+
gap: 22px;
|
|
478
|
+
padding: 56px 20px 24px;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.hs-now-playing__left {
|
|
482
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.hs-now-playing__title {
|
|
486
|
+
font-size: 22px;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.hs-now-playing__close {
|
|
490
|
+
left: 12px;
|
|
491
|
+
top: 8px;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.hs-now-playing__right {
|
|
495
|
+
height: auto;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.hs-now-playing__switch {
|
|
499
|
+
align-self: center;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.hs-now-playing__panel:has(.hs-lyrics) {
|
|
503
|
+
flex: none;
|
|
504
|
+
height: 320px;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.hs-lyrics-line {
|
|
508
|
+
font-size: 22px;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.hs-lyrics--unsynced .hs-lyrics-line {
|
|
512
|
+
font-size: 17px;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.hs-now-playing__queue-end {
|
|
516
|
+
flex-direction: column;
|
|
517
|
+
align-items: flex-end;
|
|
518
|
+
gap: 3px;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.hs-now-playing__queue-end .hs-track-row__duration {
|
|
522
|
+
width: auto;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* k09 A progress bar and spinner (k09-rm B reduced motion), k09b A skeleton, and
|
|
3
|
+
* k34 B endless loading.
|
|
4
|
+
*
|
|
5
|
+
* Bars and skeletons are still under reduced motion (f14b-r1); the spinner keeps
|
|
6
|
+
* turning at one turn per 2.7 s (k09-rm B).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/* k09 - progress bar */
|
|
11
|
+
/* ------------------------------------------------------------------ */
|
|
12
|
+
|
|
13
|
+
/* Markup: <div class="hs-progress" role="progressbar" aria-label="Downloading"
|
|
14
|
+
* aria-valuenow="42" aria-valuemin="0" aria-valuemax="100"><span
|
|
15
|
+
* class="hs-progress__fill" style="width:42%"></span></div>. Indeterminate drops
|
|
16
|
+
* aria-valuenow and adds .hs-progress--indeterminate. Never focusable. */
|
|
17
|
+
.hs-progress {
|
|
18
|
+
position: relative;
|
|
19
|
+
height: 6px;
|
|
20
|
+
border-radius: var(--hs-radius-full);
|
|
21
|
+
background: color-mix(in srgb, var(--hs-fg) 16%, transparent);
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.hs-progress__fill {
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 0;
|
|
28
|
+
bottom: 0;
|
|
29
|
+
left: 0;
|
|
30
|
+
border-radius: var(--hs-radius-full);
|
|
31
|
+
background: var(--hs-accent-bg);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.hs-progress--indeterminate .hs-progress__fill {
|
|
35
|
+
width: 40%;
|
|
36
|
+
animation: hs-progress-slide 1.4s var(--hs-ease) infinite;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@keyframes hs-progress-slide {
|
|
40
|
+
from {
|
|
41
|
+
left: -40%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
to {
|
|
45
|
+
left: 100%;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ------------------------------------------------------------------ */
|
|
50
|
+
/* k09 - spinner */
|
|
51
|
+
/* ------------------------------------------------------------------ */
|
|
52
|
+
|
|
53
|
+
/* role="status" with visually hidden "Loading"; inside a button the button keeps its
|
|
54
|
+
* label and sets aria-busy instead (k09 board notes). */
|
|
55
|
+
.hs-spinner {
|
|
56
|
+
display: inline-block;
|
|
57
|
+
flex: none;
|
|
58
|
+
width: 16px;
|
|
59
|
+
height: 16px;
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
border: 2px solid color-mix(in srgb, var(--hs-fg) 16%, transparent);
|
|
62
|
+
border-top-color: var(--hs-accent-bg);
|
|
63
|
+
border-radius: 50%;
|
|
64
|
+
animation: hs-spin 0.9s linear infinite;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.hs-spinner--24 {
|
|
68
|
+
width: 24px;
|
|
69
|
+
height: 24px;
|
|
70
|
+
border-width: 3px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* The 48 px boot spinner is used by the first-run setup screen (p27). */
|
|
74
|
+
.hs-spinner--48 {
|
|
75
|
+
width: 48px;
|
|
76
|
+
height: 48px;
|
|
77
|
+
border-width: 4px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@keyframes hs-spin {
|
|
81
|
+
to {
|
|
82
|
+
transform: rotate(360deg);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Inside suggested buttons and the play disc the ring is the accent foreground at 25%
|
|
87
|
+
* with an accent-foreground arc (k09); a destructive button does the same in its own
|
|
88
|
+
* foreground (busy-rule: the spinner takes the button's own colours). */
|
|
89
|
+
.hs-button--suggested .hs-spinner,
|
|
90
|
+
.hs-play-button .hs-spinner {
|
|
91
|
+
border-color: rgb(34 27 0 / 25%);
|
|
92
|
+
border-top-color: var(--hs-accent-fg);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.hs-button--destructive .hs-spinner {
|
|
96
|
+
border-color: color-mix(in srgb, var(--hs-destructive-fg) 25%, transparent);
|
|
97
|
+
border-top-color: var(--hs-destructive-fg);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* p19b, p19-r1: the play disc's fetching spinner is 24 px with a 3 px ring. */
|
|
101
|
+
.hs-play-button[aria-busy='true'] .hs-spinner {
|
|
102
|
+
width: 24px;
|
|
103
|
+
height: 24px;
|
|
104
|
+
border-width: 3px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* ------------------------------------------------------------------ */
|
|
108
|
+
/* k09b - skeleton */
|
|
109
|
+
/* ------------------------------------------------------------------ */
|
|
110
|
+
|
|
111
|
+
/* Holds the space of the real item and is aria-hidden (k34). Content radii come from the
|
|
112
|
+
* component it stands in for. */
|
|
113
|
+
.hs-skeleton {
|
|
114
|
+
display: block;
|
|
115
|
+
border-radius: 4px;
|
|
116
|
+
background: linear-gradient(
|
|
117
|
+
100deg,
|
|
118
|
+
var(--hs-skeleton-base) 30%,
|
|
119
|
+
var(--hs-skeleton-band) 50%,
|
|
120
|
+
var(--hs-skeleton-base) 70%
|
|
121
|
+
)
|
|
122
|
+
0 0 / 300% 100%;
|
|
123
|
+
animation: hs-shimmer 1.6s linear infinite;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@keyframes hs-shimmer {
|
|
127
|
+
from {
|
|
128
|
+
background-position: 100% 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
to {
|
|
132
|
+
background-position: -50% 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* ------------------------------------------------------------------ */
|
|
137
|
+
/* k34 - endless loading */
|
|
138
|
+
/* ------------------------------------------------------------------ */
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* The list region takes .hs-endless and aria-busy="true" while the next page loads; the
|
|
142
|
+
* placeholder items are .hs-skeleton shapes of the real rows or cards, inside an
|
|
143
|
+
* aria-hidden .hs-endless__placeholder, so they hold the space. The polite "Loading..."
|
|
144
|
+
* status is a .hs-visually-hidden element with role="status". There is no "Load more"
|
|
145
|
+
* button, and reaching the true end shows nothing extra.
|
|
146
|
+
*/
|
|
147
|
+
.hs-endless {
|
|
148
|
+
position: relative;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* The placeholder wrapper adds no box of its own, so the skeletons lay out in the list. */
|
|
152
|
+
.hs-endless__placeholder {
|
|
153
|
+
display: contents;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ------------------------------------------------------------------ */
|
|
157
|
+
/* Reduced motion (k09-rm B, f14b-r1) */
|
|
158
|
+
/* ------------------------------------------------------------------ */
|
|
159
|
+
|
|
160
|
+
@media (prefers-reduced-motion: reduce) {
|
|
161
|
+
.hs-progress--indeterminate .hs-progress__fill {
|
|
162
|
+
animation: none;
|
|
163
|
+
left: 30%;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.hs-skeleton {
|
|
167
|
+
animation: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.hs-spinner {
|
|
171
|
+
animation-duration: 2.7s;
|
|
172
|
+
}
|
|
173
|
+
}
|