sid-ui 0.1.3 → 0.2.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.
@@ -0,0 +1,343 @@
1
+ /* Chip — a compact, rounded label. soft, filled, or outlined in ten colors; selected chips take
2
+ the accent and grow a check; removed chips collapse before they leave. */
3
+
4
+ .os-chip {
5
+ --_h: 2rem;
6
+ --_pad: 0.75rem;
7
+ --_font: 0.875rem;
8
+ --_bg: color-mix(in srgb, var(--color-text-primary) 7%, transparent);
9
+ --_fg: var(--color-text-primary);
10
+ --_icon: var(--color-icon-secondary, var(--color-text-secondary));
11
+ --_line: transparent;
12
+ display: inline-grid;
13
+ grid-template-columns: 1fr;
14
+ vertical-align: middle;
15
+ max-width: 100%;
16
+ transition:
17
+ grid-template-columns 0.18s var(--ease-standard),
18
+ opacity 0.18s var(--ease-standard),
19
+ transform 0.18s var(--ease-standard);
20
+ animation: os-chip-in 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
21
+ }
22
+
23
+ .os-chip-sm {
24
+ --_h: 1.625rem;
25
+ --_pad: 0.625rem;
26
+ --_font: 0.78rem;
27
+ }
28
+
29
+ .os-chip-lg {
30
+ --_h: 2.375rem;
31
+ --_pad: 1rem;
32
+ --_font: 0.9375rem;
33
+ }
34
+
35
+ .os-chip-inner {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ min-width: 0;
39
+ height: var(--_h);
40
+ overflow: hidden;
41
+ border-radius: var(--radius-full);
42
+ background: var(--_bg);
43
+ color: var(--_fg);
44
+ box-shadow: inset 0 0 0 1px var(--_line);
45
+ white-space: nowrap;
46
+ transition:
47
+ background-color 0.15s var(--ease-standard),
48
+ color 0.15s var(--ease-standard),
49
+ box-shadow 0.15s var(--ease-standard),
50
+ transform 0.15s var(--ease-standard);
51
+ }
52
+
53
+ .os-chip-main {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ min-width: 0;
57
+ height: 100%;
58
+ padding: 0 var(--_pad);
59
+ border: 0;
60
+ border-radius: inherit;
61
+ background: none;
62
+ color: inherit;
63
+ font: inherit;
64
+ font-size: var(--_font);
65
+ font-weight: var(--font-weight-medium);
66
+ line-height: 1;
67
+ text-decoration: none;
68
+ }
69
+
70
+ button.os-chip-main,
71
+ a.os-chip-main {
72
+ cursor: pointer;
73
+ }
74
+
75
+ .os-chip:has(button.os-chip-main:hover, a.os-chip-main:hover) .os-chip-inner {
76
+ background: color-mix(in srgb, var(--_bg), var(--_fg) 9%);
77
+ }
78
+
79
+ .os-chip:has(button.os-chip-main:active, a.os-chip-main:active) .os-chip-inner {
80
+ transform: scale(0.96);
81
+ }
82
+
83
+ .os-chip-main:focus-visible,
84
+ .os-chip-remove:focus-visible {
85
+ outline: 2px solid var(--color-accent);
86
+ outline-offset: -2px;
87
+ }
88
+
89
+ .os-chip-label {
90
+ overflow: hidden;
91
+ text-overflow: ellipsis;
92
+ }
93
+
94
+ .os-chip-start {
95
+ display: inline-flex;
96
+ align-items: center;
97
+ margin-inline: -0.125rem 0.375rem;
98
+ color: var(--_icon);
99
+ }
100
+
101
+ .os-chip-start > svg,
102
+ .os-chip-start > span:has(> svg) {
103
+ width: 1.05em;
104
+ height: 1.05em;
105
+ }
106
+
107
+ /* An avatar tucks into the curve. */
108
+ .os-chip-start:has(img, [role="img"]) {
109
+ margin-inline-start: calc(-1 * var(--_pad) + 0.25rem);
110
+ }
111
+
112
+ .os-chip-count {
113
+ margin-inline-start: 0.375rem;
114
+ padding: 0.125rem 0.375rem;
115
+ border-radius: var(--radius-full);
116
+ background: color-mix(in srgb, currentColor 13%, transparent);
117
+ font-size: 0.72em;
118
+ font-variant-numeric: tabular-nums;
119
+ font-weight: var(--font-weight-semibold);
120
+ }
121
+
122
+ /* The check grows in from zero width when the chip is selected. */
123
+ .os-chip-check {
124
+ display: grid;
125
+ grid-template-columns: 0fr;
126
+ margin-inline-start: -0.125rem;
127
+ transition: grid-template-columns 0.22s cubic-bezier(0.34, 1.4, 0.64, 1);
128
+ }
129
+
130
+ .os-chip-check > span {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ min-width: 0;
134
+ overflow: hidden;
135
+ }
136
+
137
+ .os-chip-check svg {
138
+ flex-shrink: 0;
139
+ width: 1em;
140
+ height: 1em;
141
+ margin-inline-end: 0.3rem;
142
+ stroke-width: 2.6;
143
+ transform: scale(0.4);
144
+ opacity: 0;
145
+ transition:
146
+ transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
147
+ opacity 0.15s;
148
+ }
149
+
150
+ .os-chip-selected .os-chip-check {
151
+ grid-template-columns: 1fr;
152
+ }
153
+
154
+ .os-chip-selected .os-chip-check svg {
155
+ transform: none;
156
+ opacity: 1;
157
+ }
158
+
159
+ /* Remove */
160
+ .os-chip-removable .os-chip-main {
161
+ padding-inline-end: 0.25rem;
162
+ }
163
+
164
+ .os-chip-remove {
165
+ display: grid;
166
+ place-items: center;
167
+ flex-shrink: 0;
168
+ width: calc(var(--_h) - 0.625rem);
169
+ height: calc(var(--_h) - 0.625rem);
170
+ margin-inline-end: 0.3125rem;
171
+ padding: 0;
172
+ border: 0;
173
+ border-radius: var(--radius-full);
174
+ background: transparent;
175
+ color: inherit;
176
+ opacity: 0.65;
177
+ cursor: pointer;
178
+ transition:
179
+ background-color 0.15s,
180
+ opacity 0.15s;
181
+ }
182
+
183
+ .os-chip-remove svg {
184
+ width: 0.85em;
185
+ height: 0.85em;
186
+ }
187
+
188
+ .os-chip-remove:hover {
189
+ opacity: 1;
190
+ background: color-mix(in srgb, currentColor 14%, transparent);
191
+ }
192
+
193
+ .os-chip-leaving {
194
+ grid-template-columns: 0fr;
195
+ opacity: 0;
196
+ transform: scale(0.85);
197
+ pointer-events: none;
198
+ }
199
+
200
+ .os-chip-disabled {
201
+ opacity: 0.45;
202
+ }
203
+
204
+ .os-chip-disabled .os-chip-main,
205
+ .os-chip-disabled .os-chip-remove {
206
+ cursor: not-allowed;
207
+ }
208
+
209
+ /* ---------- Colors ---------- */
210
+
211
+ .os-chip-blue {
212
+ --_c-bg: var(--color-background-blue);
213
+ --_c-fg: var(--color-text-blue);
214
+ --_c-icon: var(--color-icon-blue);
215
+ --_c-line: var(--color-border-blue);
216
+ }
217
+ .os-chip-green {
218
+ --_c-bg: var(--color-background-green);
219
+ --_c-fg: var(--color-text-green);
220
+ --_c-icon: var(--color-icon-green);
221
+ --_c-line: var(--color-border-green);
222
+ }
223
+ .os-chip-yellow {
224
+ --_c-bg: var(--color-background-yellow);
225
+ --_c-fg: var(--color-text-yellow);
226
+ --_c-icon: var(--color-icon-yellow);
227
+ --_c-line: var(--color-border-yellow);
228
+ }
229
+ .os-chip-red {
230
+ --_c-bg: var(--color-background-red);
231
+ --_c-fg: var(--color-text-red);
232
+ --_c-icon: var(--color-icon-red);
233
+ --_c-line: var(--color-border-red);
234
+ }
235
+ .os-chip-purple {
236
+ --_c-bg: var(--color-background-purple);
237
+ --_c-fg: var(--color-text-purple);
238
+ --_c-icon: var(--color-icon-purple);
239
+ --_c-line: var(--color-border-purple);
240
+ }
241
+ .os-chip-pink {
242
+ --_c-bg: var(--color-background-pink);
243
+ --_c-fg: var(--color-text-pink);
244
+ --_c-icon: var(--color-icon-pink);
245
+ --_c-line: var(--color-border-pink);
246
+ }
247
+ .os-chip-teal {
248
+ --_c-bg: var(--color-background-teal);
249
+ --_c-fg: var(--color-text-teal);
250
+ --_c-icon: var(--color-icon-teal);
251
+ --_c-line: var(--color-border-teal);
252
+ }
253
+ .os-chip-orange {
254
+ --_c-bg: var(--color-background-orange);
255
+ --_c-fg: var(--color-text-orange);
256
+ --_c-icon: var(--color-icon-orange);
257
+ --_c-line: var(--color-border-orange);
258
+ }
259
+ .os-chip-cyan {
260
+ --_c-bg: var(--color-background-cyan);
261
+ --_c-fg: var(--color-text-cyan);
262
+ --_c-icon: var(--color-icon-cyan);
263
+ --_c-line: var(--color-border-cyan);
264
+ }
265
+
266
+ .os-chip:not(.os-chip-neutral).os-chip-filled {
267
+ --_bg: var(--_c-bg);
268
+ --_fg: var(--_c-fg);
269
+ --_icon: var(--_c-icon);
270
+ }
271
+
272
+ .os-chip:not(.os-chip-neutral).os-chip-soft {
273
+ --_bg: color-mix(in srgb, var(--_c-bg) 34%, transparent);
274
+ --_fg: var(--_c-fg);
275
+ --_icon: var(--_c-icon);
276
+ }
277
+
278
+ .os-chip-neutral.os-chip-filled {
279
+ --_bg: color-mix(in srgb, var(--color-text-primary) 11%, transparent);
280
+ }
281
+
282
+ .os-chip-outlined {
283
+ --_bg: var(--color-background-surface);
284
+ --_line: color-mix(in srgb, var(--color-text-primary) 18%, transparent);
285
+ }
286
+
287
+ .os-chip:not(.os-chip-neutral).os-chip-outlined {
288
+ --_line: var(--_c-line);
289
+ --_icon: var(--_c-icon);
290
+ }
291
+
292
+ /* Selected beats color: the accent says “on”. */
293
+ .os-chip.os-chip-selected {
294
+ --_bg: var(--color-accent-muted);
295
+ --_fg: var(--color-accent);
296
+ --_icon: var(--color-accent);
297
+ --_line: color-mix(in srgb, var(--color-accent) 40%, transparent);
298
+ }
299
+
300
+ /* ---------- Group ---------- */
301
+
302
+ .os-chip-group {
303
+ display: flex;
304
+ flex-wrap: wrap;
305
+ align-items: center;
306
+ gap: var(--spacing-2);
307
+ }
308
+
309
+ .os-chip-group-scroll {
310
+ flex-wrap: nowrap;
311
+ overflow-x: auto;
312
+ scrollbar-width: none;
313
+ padding-block: 2px;
314
+ -webkit-mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 24px), transparent);
315
+ mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 24px), transparent);
316
+ padding-inline: 12px 24px;
317
+ margin-inline: -12px;
318
+ }
319
+
320
+ .os-chip-group-scroll::-webkit-scrollbar {
321
+ display: none;
322
+ }
323
+
324
+ .os-chip-group-scroll > .os-chip {
325
+ flex-shrink: 0;
326
+ }
327
+
328
+ @keyframes os-chip-in {
329
+ from {
330
+ opacity: 0;
331
+ transform: scale(0.85);
332
+ }
333
+ }
334
+
335
+ @media (prefers-reduced-motion: reduce) {
336
+ .os-chip,
337
+ .os-chip-inner,
338
+ .os-chip-check,
339
+ .os-chip-check svg {
340
+ transition: none;
341
+ animation: none;
342
+ }
343
+ }
@@ -1,9 +1,15 @@
1
- /* CodeInput — one round cell per character. A filled cell pops in, the active cell lifts and
2
- shows a blinking caret, a wrong code shakes once, and a right one ripples green across the row.
3
- Motion uses only duration/ease tokens and stands down for prefers-reduced-motion. */
1
+ /* CodeInput — one clean cell per character. Each digit is a drum that spins from 0 (or from the
2
+ digit it replaces) and settles with a slight overshoot, like a phone's scroll picker. The active
3
+ cell takes the accent ring, a wrong code shakes once, and a right one lifts green cell by cell.
4
+ Motion stands down for prefers-reduced-motion. */
4
5
 
5
6
  .os-code {
6
- --_cell: var(--spacing-12);
7
+ --_cell: 3.25rem;
8
+ --_cell-h: 4rem;
9
+ --_radius: 0.875rem;
10
+ --_ok: var(--color-data-categorical-green);
11
+ --_bad: var(--color-data-categorical-red);
12
+ --_line: color-mix(in srgb, var(--color-text-primary) 15%, transparent);
7
13
  display: flex;
8
14
  flex-direction: column;
9
15
  gap: var(--spacing-2);
@@ -11,11 +17,15 @@
11
17
  }
12
18
 
13
19
  .os-code-sm {
14
- --_cell: var(--spacing-10);
20
+ --_cell: 2.625rem;
21
+ --_cell-h: 3.25rem;
22
+ --_radius: 0.75rem;
15
23
  }
16
24
 
17
25
  .os-code-lg {
18
- --_cell: calc(var(--spacing-12) + var(--spacing-2));
26
+ --_cell: 3.75rem;
27
+ --_cell-h: 4.625rem;
28
+ --_radius: 1rem;
19
29
  }
20
30
 
21
31
  .os-code-label {
@@ -48,46 +58,41 @@
48
58
  position: relative;
49
59
  flex: 0 1 auto;
50
60
  width: var(--_cell);
61
+ height: var(--_cell-h);
51
62
  min-width: 0;
52
- aspect-ratio: 1;
53
- border-radius: var(--radius-full);
63
+ border-radius: var(--_radius);
54
64
  background: var(--color-background-surface);
55
- box-shadow: inset 0 0 0 1px var(--color-border-emphasized);
65
+ box-shadow:
66
+ inset 0 0 0 1.5px var(--_line),
67
+ 0 1px 2px color-mix(in srgb, var(--color-text-primary) 6%, transparent);
56
68
  transition:
57
- box-shadow var(--duration-fast) var(--ease-standard),
58
- background-color var(--duration-fast) var(--ease-standard),
59
- transform var(--duration-medium) var(--ease-standard);
69
+ box-shadow 0.2s var(--ease-standard),
70
+ transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
60
71
  }
61
72
 
62
73
  .os-code-cell:hover {
63
- box-shadow: inset 0 0 0 1px var(--color-text-disabled);
64
- }
65
-
66
- /* The active cell lifts slightly and takes the accent ring. */
67
- .os-code-cell:focus-within {
68
- background: var(--color-accent-muted);
69
- box-shadow:
70
- inset 0 0 0 2px var(--color-accent),
71
- 0 var(--spacing-1) var(--spacing-3) var(--color-shadow);
72
- transform: translateY(calc(-1 * var(--spacing-0-5))) scale(1.06);
74
+ --_line: color-mix(in srgb, var(--color-text-primary) 28%, transparent);
73
75
  }
74
76
 
75
- /* A cell that holds a character keeps a soft accent tint, and pops each time it fills. */
77
+ /* Filled cells keep a firmer edge — no tint. */
76
78
  .os-code-cell[data-filled="true"] {
77
- background: var(--color-accent-muted);
78
- box-shadow: inset 0 0 0 1px var(--color-border-blue);
79
- animation: os-code-pop var(--duration-medium) var(--ease-standard);
79
+ --_line: color-mix(in srgb, var(--color-text-primary) 32%, transparent);
80
80
  }
81
81
 
82
- .os-code-cell[data-filled="true"]:focus-within {
82
+ /* The active cell: accent ring with a soft halo, lifted a touch. */
83
+ .os-code-cell:focus-within {
83
84
  box-shadow:
84
85
  inset 0 0 0 2px var(--color-accent),
85
- 0 var(--spacing-1) var(--spacing-3) var(--color-shadow);
86
+ 0 0 0 4px color-mix(in srgb, var(--color-accent) 16%, transparent),
87
+ 0 6px 16px -6px color-mix(in srgb, var(--color-accent) 45%, transparent);
88
+ transform: translateY(-2px);
86
89
  }
87
90
 
91
+ /* The real input sits on top for typing and selection; the face below draws the character. */
88
92
  .os-code-input {
89
93
  position: absolute;
90
94
  inset: 0;
95
+ z-index: 1;
91
96
  width: 100%;
92
97
  height: 100%;
93
98
  min-width: 0;
@@ -97,67 +102,112 @@
97
102
  border-radius: inherit;
98
103
  background: transparent;
99
104
  outline: none;
105
+ color: transparent;
106
+ font-size: 1rem;
107
+ text-align: center;
108
+ caret-color: transparent;
109
+ cursor: text;
110
+ }
111
+
112
+ .os-code-input::selection {
113
+ background: transparent;
114
+ }
115
+
116
+ .os-code-face {
117
+ position: absolute;
118
+ inset: 0;
119
+ display: grid;
120
+ place-items: center;
121
+ overflow: hidden;
122
+ border-radius: inherit;
100
123
  color: var(--color-text-primary);
101
124
  font-family: var(--font-family-body);
102
- font-size: var(--font-size-2xl);
125
+ font-size: 1.75rem;
103
126
  font-weight: var(--font-weight-semibold);
104
127
  font-variant-numeric: tabular-nums;
105
- text-align: center;
106
- text-transform: uppercase;
107
- caret-color: transparent;
108
- cursor: text;
128
+ line-height: 1;
129
+ pointer-events: none;
130
+ }
131
+
132
+ .os-code-sm .os-code-face {
133
+ font-size: 1.375rem;
134
+ }
135
+
136
+ .os-code-lg .os-code-face {
137
+ font-size: 2.125rem;
138
+ }
139
+
140
+ /* The drum: ten rows, each a cell tall, faded toward the edges like a picker wheel. */
141
+ .os-code-face-drum {
142
+ place-items: start center;
143
+ -webkit-mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
144
+ mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
145
+ }
146
+
147
+ .os-code-drum {
148
+ display: flex;
149
+ flex-direction: column;
150
+ transform: translateY(calc(var(--os-code-roll, 0) * -1 * var(--_cell-h)));
151
+ transition-property: transform;
152
+ transition-timing-function: cubic-bezier(0.2, 1.25, 0.35, 1);
153
+ will-change: transform;
109
154
  }
110
155
 
111
- .os-code-sm .os-code-input {
112
- font-size: var(--font-size-xl);
156
+ .os-code-digit {
157
+ display: grid;
158
+ place-items: center;
159
+ height: var(--_cell-h);
113
160
  }
114
161
 
115
- .os-code-lg .os-code-input {
116
- font-size: var(--font-size-3xl);
162
+ /* Letters drop in from above and bounce once. */
163
+ .os-code-letter {
164
+ animation: os-code-drop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
117
165
  }
118
166
 
119
167
  /* A blinking bar stands in for the caret while an empty cell is active. */
120
168
  .os-code-cell[data-filled="false"]:focus-within::after {
121
169
  content: "";
122
170
  position: absolute;
123
- top: 28%;
124
- bottom: 28%;
171
+ top: 30%;
172
+ bottom: 30%;
125
173
  left: 50%;
126
- width: var(--spacing-0-5);
174
+ width: 2px;
127
175
  border-radius: var(--radius-full);
128
176
  background: var(--color-accent);
129
177
  transform: translateX(-50%);
130
178
  pointer-events: none;
131
- animation: os-code-caret 1s var(--ease-standard) infinite;
179
+ animation: os-code-caret 1.1s steps(1, end) infinite;
132
180
  }
133
181
 
134
- /* Error: one shake and a red ring. */
182
+ /* Error: one shake, red edges and digits. */
135
183
  .os-code[data-status="error"] .os-code-cell,
136
184
  .os-code[data-status="error"] .os-code-cell:focus-within {
137
- background: var(--color-error-muted);
138
- box-shadow: inset 0 0 0 2px var(--color-error);
185
+ box-shadow:
186
+ inset 0 0 0 2px var(--_bad),
187
+ 0 0 0 4px color-mix(in srgb, var(--_bad) 14%, transparent);
188
+ transform: none;
139
189
  }
140
190
 
141
191
  .os-code[data-status="error"] .os-code-cells {
142
- animation: os-code-shake var(--duration-fast) var(--ease-standard) 3;
192
+ animation: os-code-shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
143
193
  }
144
194
 
145
- .os-code[data-status="error"] .os-code-input {
146
- color: var(--color-error);
195
+ .os-code[data-status="error"] .os-code-face {
196
+ color: var(--_bad);
147
197
  }
148
198
 
149
- /* Success: green, each cell a beat after the one before. */
199
+ /* Success: green, each cell lifting a beat after the one before. */
150
200
  .os-code[data-status="success"] .os-code-cell,
151
201
  .os-code[data-status="success"] .os-code-cell:focus-within {
152
- background: var(--color-success-muted);
153
- box-shadow: inset 0 0 0 2px var(--color-success);
154
- transform: none;
155
- animation: os-code-ripple var(--duration-medium) var(--ease-standard) both;
156
- animation-delay: calc(var(--os-code-index) * var(--duration-fast));
202
+ box-shadow:
203
+ inset 0 0 0 2px var(--_ok),
204
+ 0 0 0 4px color-mix(in srgb, var(--_ok) 14%, transparent);
205
+ animation: os-code-hop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
206
+ animation-delay: calc(var(--os-code-index) * 60ms);
157
207
  }
158
208
 
159
- .os-code[data-status="success"] .os-code-input {
160
- color: var(--color-success);
209
+ .os-code[data-status="success"] .os-code-face {
210
+ color: var(--_ok);
161
211
  }
162
212
 
163
213
  .os-code-input:disabled {
@@ -168,61 +218,64 @@
168
218
  opacity: 0.45;
169
219
  }
170
220
 
171
- @keyframes os-code-pop {
172
- 0% {
173
- transform: scale(0.82);
174
- }
175
- 60% {
176
- transform: scale(1.12);
177
- }
178
- 100% {
179
- transform: scale(1);
221
+ @keyframes os-code-drop {
222
+ from {
223
+ opacity: 0;
224
+ transform: translateY(-70%);
180
225
  }
181
226
  }
182
227
 
183
228
  @keyframes os-code-caret {
184
- 0%,
185
- 45% {
229
+ 0% {
186
230
  opacity: 1;
187
231
  }
188
- 55%,
189
- 100% {
232
+ 50% {
190
233
  opacity: 0;
191
234
  }
192
235
  }
193
236
 
194
237
  @keyframes os-code-shake {
195
- 0%,
196
- 100% {
197
- transform: translateX(0);
238
+ 10%,
239
+ 90% {
240
+ transform: translateX(-2px);
198
241
  }
199
- 25% {
200
- transform: translateX(calc(-1 * var(--spacing-2)));
242
+ 20%,
243
+ 80% {
244
+ transform: translateX(4px);
201
245
  }
202
- 75% {
203
- transform: translateX(var(--spacing-2));
246
+ 30%,
247
+ 50%,
248
+ 70% {
249
+ transform: translateX(-7px);
250
+ }
251
+ 40%,
252
+ 60% {
253
+ transform: translateX(7px);
204
254
  }
205
255
  }
206
256
 
207
- @keyframes os-code-ripple {
208
- 0% {
209
- transform: scale(1);
210
- }
211
- 50% {
212
- transform: scale(1.18);
213
- }
257
+ @keyframes os-code-hop {
258
+ 0%,
214
259
  100% {
215
- transform: scale(1);
260
+ transform: translateY(0);
261
+ }
262
+ 45% {
263
+ transform: translateY(-8px);
216
264
  }
217
265
  }
218
266
 
219
267
  @media (prefers-reduced-motion: reduce) {
220
268
  .os-code-cell,
221
- .os-code-cells {
269
+ .os-code-cells,
270
+ .os-code-letter {
222
271
  animation: none !important;
223
272
  transition: none;
224
273
  }
225
274
 
275
+ .os-code-drum {
276
+ transition-duration: 0s !important;
277
+ }
278
+
226
279
  .os-code-cell:focus-within {
227
280
  transform: none;
228
281
  }