audex 1.0.7a3__py3-none-any.whl

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 (192) hide show
  1. audex/__init__.py +9 -0
  2. audex/__main__.py +7 -0
  3. audex/cli/__init__.py +189 -0
  4. audex/cli/apis/__init__.py +12 -0
  5. audex/cli/apis/init/__init__.py +34 -0
  6. audex/cli/apis/init/gencfg.py +130 -0
  7. audex/cli/apis/init/setup.py +330 -0
  8. audex/cli/apis/init/vprgroup.py +125 -0
  9. audex/cli/apis/serve.py +141 -0
  10. audex/cli/args.py +356 -0
  11. audex/cli/exceptions.py +44 -0
  12. audex/cli/helper/__init__.py +0 -0
  13. audex/cli/helper/ansi.py +193 -0
  14. audex/cli/helper/display.py +288 -0
  15. audex/config/__init__.py +64 -0
  16. audex/config/core/__init__.py +30 -0
  17. audex/config/core/app.py +29 -0
  18. audex/config/core/audio.py +45 -0
  19. audex/config/core/logging.py +163 -0
  20. audex/config/core/session.py +11 -0
  21. audex/config/helper/__init__.py +1 -0
  22. audex/config/helper/client/__init__.py +1 -0
  23. audex/config/helper/client/http.py +28 -0
  24. audex/config/helper/client/websocket.py +21 -0
  25. audex/config/helper/provider/__init__.py +1 -0
  26. audex/config/helper/provider/dashscope.py +13 -0
  27. audex/config/helper/provider/unisound.py +18 -0
  28. audex/config/helper/provider/xfyun.py +23 -0
  29. audex/config/infrastructure/__init__.py +31 -0
  30. audex/config/infrastructure/cache.py +51 -0
  31. audex/config/infrastructure/database.py +48 -0
  32. audex/config/infrastructure/recorder.py +32 -0
  33. audex/config/infrastructure/store.py +19 -0
  34. audex/config/provider/__init__.py +18 -0
  35. audex/config/provider/transcription.py +109 -0
  36. audex/config/provider/vpr.py +99 -0
  37. audex/container.py +40 -0
  38. audex/entity/__init__.py +468 -0
  39. audex/entity/doctor.py +109 -0
  40. audex/entity/doctor.pyi +51 -0
  41. audex/entity/fields.py +401 -0
  42. audex/entity/segment.py +115 -0
  43. audex/entity/segment.pyi +38 -0
  44. audex/entity/session.py +133 -0
  45. audex/entity/session.pyi +47 -0
  46. audex/entity/utterance.py +142 -0
  47. audex/entity/utterance.pyi +48 -0
  48. audex/entity/vp.py +68 -0
  49. audex/entity/vp.pyi +35 -0
  50. audex/exceptions.py +157 -0
  51. audex/filters/__init__.py +692 -0
  52. audex/filters/generated/__init__.py +21 -0
  53. audex/filters/generated/doctor.py +987 -0
  54. audex/filters/generated/segment.py +723 -0
  55. audex/filters/generated/session.py +978 -0
  56. audex/filters/generated/utterance.py +939 -0
  57. audex/filters/generated/vp.py +815 -0
  58. audex/helper/__init__.py +1 -0
  59. audex/helper/hash.py +33 -0
  60. audex/helper/mixin.py +65 -0
  61. audex/helper/net.py +19 -0
  62. audex/helper/settings/__init__.py +830 -0
  63. audex/helper/settings/fields.py +317 -0
  64. audex/helper/stream.py +153 -0
  65. audex/injectors/__init__.py +1 -0
  66. audex/injectors/config.py +12 -0
  67. audex/injectors/lifespan.py +7 -0
  68. audex/lib/__init__.py +1 -0
  69. audex/lib/cache/__init__.py +383 -0
  70. audex/lib/cache/inmemory.py +513 -0
  71. audex/lib/database/__init__.py +83 -0
  72. audex/lib/database/sqlite.py +406 -0
  73. audex/lib/exporter.py +189 -0
  74. audex/lib/injectors/__init__.py +1 -0
  75. audex/lib/injectors/cache.py +25 -0
  76. audex/lib/injectors/container.py +47 -0
  77. audex/lib/injectors/exporter.py +26 -0
  78. audex/lib/injectors/recorder.py +33 -0
  79. audex/lib/injectors/server.py +17 -0
  80. audex/lib/injectors/session.py +18 -0
  81. audex/lib/injectors/sqlite.py +24 -0
  82. audex/lib/injectors/store.py +13 -0
  83. audex/lib/injectors/transcription.py +42 -0
  84. audex/lib/injectors/usb.py +12 -0
  85. audex/lib/injectors/vpr.py +65 -0
  86. audex/lib/injectors/wifi.py +7 -0
  87. audex/lib/recorder.py +844 -0
  88. audex/lib/repos/__init__.py +149 -0
  89. audex/lib/repos/container.py +23 -0
  90. audex/lib/repos/database/__init__.py +1 -0
  91. audex/lib/repos/database/sqlite.py +672 -0
  92. audex/lib/repos/decorators.py +74 -0
  93. audex/lib/repos/doctor.py +286 -0
  94. audex/lib/repos/segment.py +302 -0
  95. audex/lib/repos/session.py +285 -0
  96. audex/lib/repos/tables/__init__.py +70 -0
  97. audex/lib/repos/tables/doctor.py +137 -0
  98. audex/lib/repos/tables/segment.py +113 -0
  99. audex/lib/repos/tables/session.py +140 -0
  100. audex/lib/repos/tables/utterance.py +131 -0
  101. audex/lib/repos/tables/vp.py +102 -0
  102. audex/lib/repos/utterance.py +288 -0
  103. audex/lib/repos/vp.py +286 -0
  104. audex/lib/restful.py +251 -0
  105. audex/lib/server/__init__.py +97 -0
  106. audex/lib/server/auth.py +98 -0
  107. audex/lib/server/handlers.py +248 -0
  108. audex/lib/server/templates/index.html.j2 +226 -0
  109. audex/lib/server/templates/login.html.j2 +111 -0
  110. audex/lib/server/templates/static/script.js +68 -0
  111. audex/lib/server/templates/static/style.css +579 -0
  112. audex/lib/server/types.py +123 -0
  113. audex/lib/session.py +503 -0
  114. audex/lib/store/__init__.py +238 -0
  115. audex/lib/store/localfile.py +411 -0
  116. audex/lib/transcription/__init__.py +33 -0
  117. audex/lib/transcription/dashscope.py +525 -0
  118. audex/lib/transcription/events.py +62 -0
  119. audex/lib/usb.py +554 -0
  120. audex/lib/vpr/__init__.py +38 -0
  121. audex/lib/vpr/unisound/__init__.py +185 -0
  122. audex/lib/vpr/unisound/types.py +469 -0
  123. audex/lib/vpr/xfyun/__init__.py +483 -0
  124. audex/lib/vpr/xfyun/types.py +679 -0
  125. audex/lib/websocket/__init__.py +8 -0
  126. audex/lib/websocket/connection.py +485 -0
  127. audex/lib/websocket/pool.py +991 -0
  128. audex/lib/wifi.py +1146 -0
  129. audex/lifespan.py +75 -0
  130. audex/service/__init__.py +27 -0
  131. audex/service/decorators.py +73 -0
  132. audex/service/doctor/__init__.py +652 -0
  133. audex/service/doctor/const.py +36 -0
  134. audex/service/doctor/exceptions.py +96 -0
  135. audex/service/doctor/types.py +54 -0
  136. audex/service/export/__init__.py +236 -0
  137. audex/service/export/const.py +17 -0
  138. audex/service/export/exceptions.py +34 -0
  139. audex/service/export/types.py +21 -0
  140. audex/service/injectors/__init__.py +1 -0
  141. audex/service/injectors/container.py +53 -0
  142. audex/service/injectors/doctor.py +34 -0
  143. audex/service/injectors/export.py +27 -0
  144. audex/service/injectors/session.py +49 -0
  145. audex/service/session/__init__.py +754 -0
  146. audex/service/session/const.py +34 -0
  147. audex/service/session/exceptions.py +67 -0
  148. audex/service/session/types.py +91 -0
  149. audex/types.py +39 -0
  150. audex/utils.py +287 -0
  151. audex/valueobj/__init__.py +81 -0
  152. audex/valueobj/common/__init__.py +1 -0
  153. audex/valueobj/common/auth.py +84 -0
  154. audex/valueobj/common/email.py +16 -0
  155. audex/valueobj/common/ops.py +22 -0
  156. audex/valueobj/common/phone.py +84 -0
  157. audex/valueobj/common/version.py +72 -0
  158. audex/valueobj/session.py +19 -0
  159. audex/valueobj/utterance.py +15 -0
  160. audex/view/__init__.py +51 -0
  161. audex/view/container.py +17 -0
  162. audex/view/decorators.py +303 -0
  163. audex/view/pages/__init__.py +1 -0
  164. audex/view/pages/dashboard/__init__.py +286 -0
  165. audex/view/pages/dashboard/wifi.py +407 -0
  166. audex/view/pages/login.py +110 -0
  167. audex/view/pages/recording.py +348 -0
  168. audex/view/pages/register.py +202 -0
  169. audex/view/pages/sessions/__init__.py +196 -0
  170. audex/view/pages/sessions/details.py +224 -0
  171. audex/view/pages/sessions/export.py +443 -0
  172. audex/view/pages/settings.py +374 -0
  173. audex/view/pages/voiceprint/__init__.py +1 -0
  174. audex/view/pages/voiceprint/enroll.py +195 -0
  175. audex/view/pages/voiceprint/update.py +195 -0
  176. audex/view/static/css/dashboard.css +452 -0
  177. audex/view/static/css/glass.css +22 -0
  178. audex/view/static/css/global.css +541 -0
  179. audex/view/static/css/login.css +386 -0
  180. audex/view/static/css/recording.css +439 -0
  181. audex/view/static/css/register.css +293 -0
  182. audex/view/static/css/sessions/styles.css +501 -0
  183. audex/view/static/css/settings.css +186 -0
  184. audex/view/static/css/voiceprint/enroll.css +43 -0
  185. audex/view/static/css/voiceprint/styles.css +209 -0
  186. audex/view/static/css/voiceprint/update.css +44 -0
  187. audex/view/static/images/logo.svg +95 -0
  188. audex/view/static/js/recording.js +42 -0
  189. audex-1.0.7a3.dist-info/METADATA +361 -0
  190. audex-1.0.7a3.dist-info/RECORD +192 -0
  191. audex-1.0.7a3.dist-info/WHEEL +4 -0
  192. audex-1.0.7a3.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,439 @@
1
+ @import "global.css";
2
+ @import "glass.css";
3
+
4
+ html, body {
5
+ margin: 0 !important;
6
+ padding: 0 !important;
7
+ overflow: hidden !important;
8
+ height: 100vh;
9
+ width: 100vw;
10
+ background: linear-gradient(135deg, #fafbfc 0%, #f8fafc 100%);
11
+ }
12
+
13
+ /* Hide scrollbars completely */
14
+ ::-webkit-scrollbar {
15
+ display: none !important;
16
+ }
17
+
18
+ * {
19
+ -ms-overflow-style: none !important;
20
+ scrollbar-width: none !important;
21
+ }
22
+
23
+ .nicegui-content {
24
+ padding: 0 !important;
25
+ margin: 0 !important;
26
+ }
27
+
28
+ .q-page {
29
+ padding: 0 !important;
30
+ margin: 0 !important;
31
+ }
32
+
33
+ /* ==================== Layout Classes ==================== */
34
+
35
+ .items-center {
36
+ align-items: center;
37
+ }
38
+
39
+ .justify-between {
40
+ justify-content: space-between;
41
+ }
42
+
43
+ .justify-end {
44
+ justify-content: flex-end;
45
+ }
46
+
47
+ .flex-1 {
48
+ flex: 1;
49
+ }
50
+
51
+ .gap-2 {
52
+ gap: 0.5rem;
53
+ }
54
+
55
+ .gap-3 {
56
+ gap: 0.75rem;
57
+ }
58
+
59
+ .gap-4 {
60
+ gap: 1rem;
61
+ }
62
+
63
+ .px-6 {
64
+ padding-left: 3rem !important;
65
+ padding-right: 3rem !important;
66
+ }
67
+
68
+ .py-3 {
69
+ padding-top: 0.75rem;
70
+ padding-bottom: 0.75rem;
71
+ }
72
+
73
+ .mb-2 {
74
+ margin-bottom: 0.5rem;
75
+ }
76
+
77
+ .mb-6 {
78
+ margin-bottom: 1.5rem;
79
+ }
80
+
81
+ .mt-3 {
82
+ margin-top: 0.75rem;
83
+ }
84
+
85
+ .mt-6 {
86
+ margin-top: 1.5rem;
87
+ }
88
+
89
+ .w-full {
90
+ width: 100%;
91
+ }
92
+
93
+ /* ==================== Typography ==================== */
94
+
95
+ .text-body2 {
96
+ font-size: 0.875rem;
97
+ line-height: 1.25rem;
98
+ }
99
+
100
+ .text-h6 {
101
+ font-size: 1.25rem;
102
+ line-height: 1.75rem;
103
+ }
104
+
105
+ .text-h5 {
106
+ font-size: 1.5rem;
107
+ line-height: 2rem;
108
+ }
109
+
110
+ .font-semibold {
111
+ font-weight: 600;
112
+ }
113
+
114
+ .font-bold {
115
+ font-weight: 700;
116
+ }
117
+
118
+ .text-grey-7 {
119
+ color: #616161;
120
+ }
121
+
122
+ .text-grey-8 {
123
+ color: #424242;
124
+ }
125
+
126
+ .text-grey-9 {
127
+ color: #212121;
128
+ }
129
+
130
+
131
+ /* ==================== Footer Glass ==================== */
132
+
133
+ .footer-glass {
134
+ position: fixed !important;
135
+ bottom: 0 !important;
136
+ left: 0 !important;
137
+ right: 0 !important;
138
+ height: 150px !important;
139
+ backdrop-filter: blur(200px) saturate(400%) !important;
140
+ -webkit-backdrop-filter: blur(200px) saturate(400%) !important;
141
+ background: linear-gradient(to top,
142
+ rgba(255, 255, 255, 0.92) 0%,
143
+ rgba(255, 255, 255, 0.65) 20%,
144
+ rgba(255, 255, 255, 0.35) 40%,
145
+ rgba(255, 255, 255, 0.12) 60%,
146
+ rgba(255, 255, 255, 0.04) 80%,
147
+ rgba(255, 255, 255, 0) 100%) !important;
148
+ border: none !important;
149
+ z-index: 999 !important;
150
+ pointer-events: none !important;
151
+ }
152
+
153
+ /* ==================== Scroll Button ==================== */
154
+
155
+ .scroll-bottom-btn {
156
+ position: fixed !important;
157
+ top: 130px !important;
158
+ right: 20px !important;
159
+ width: 48px !important;
160
+ height: 48px !important;
161
+ border-radius: 50% !important;
162
+ z-index: 1002 !important;
163
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12) !important;
164
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
165
+ }
166
+
167
+ .scroll-bottom-btn:hover {
168
+ transform: scale(1.1) !important;
169
+ box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18) !important;
170
+ background: rgba(255, 255, 255, 0.6) !important;
171
+ backdrop-filter: blur(12px) !important;
172
+ -webkit-backdrop-filter: blur(12px) !important;
173
+ }
174
+
175
+ /* ==================== Record Button ==================== */
176
+
177
+ .record-btn {
178
+ width: 80px !important;
179
+ height: 80px !important;
180
+ border-radius: 50% !important;
181
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
182
+ position: fixed !important;
183
+ bottom: 60px !important;
184
+ left: 50% !important;
185
+ transform: translateX(-50%) !important;
186
+ z-index: 1001 !important;
187
+ box-shadow: 0 8px 32px rgba(102, 126, 234, 0.25), 0 4px 16px rgba(118, 75, 162, 0.15) !important;
188
+ pointer-events: auto !important;
189
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
190
+ }
191
+
192
+ .record-btn:hover:not(:disabled) {
193
+ transform: translateX(-50%) scale(1.08) !important;
194
+ box-shadow: 0 12px 40px rgba(102, 126, 234, 0.35), 0 6px 20px rgba(118, 75, 162, 0.25) !important;
195
+ }
196
+
197
+ .record-btn:disabled {
198
+ opacity: 0.6 !important;
199
+ cursor: not-allowed !important;
200
+ }
201
+
202
+ /* Recording pulse animation */
203
+ .recording-pulse {
204
+ animation: pulse-recording 2s ease-out infinite;
205
+ }
206
+
207
+ @keyframes pulse-recording {
208
+ 0%, 100% {
209
+ box-shadow: 0 8px 32px rgba(239, 68, 68, 0.4), 0 4px 16px rgba(239, 68, 68, 0.2), 0 0 0 0 rgba(239, 68, 68, 0.7);
210
+ }
211
+ 50% {
212
+ box-shadow: 0 8px 32px rgba(239, 68, 68, 0.4), 0 4px 16px rgba(239, 68, 68, 0.2), 0 0 0 20px rgba(239, 68, 68, 0);
213
+ }
214
+ }
215
+
216
+ /* ==================== Lyrics Container ==================== */
217
+
218
+ .lyrics-container {
219
+ position: fixed !important;
220
+ top: 0 !important;
221
+ left: 0 !important;
222
+ right: 0 !important;
223
+ bottom: 0 !important;
224
+ width: 100vw !important;
225
+ height: 100vh !important;
226
+ padding: 130px 20px 170px 20px !important;
227
+ overflow-y: auto !important;
228
+ overflow-x: hidden !important;
229
+ scroll-behavior: smooth !important;
230
+ background: transparent !important;
231
+ z-index: 1 !important;
232
+ }
233
+
234
+ /* ==================== Utterances ==================== */
235
+
236
+ .utterance-item {
237
+ width: 100%;
238
+ display: flex;
239
+ justify-content: center;
240
+ align-items: center;
241
+ padding: 16px 0;
242
+ transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
243
+ }
244
+
245
+ .utterance-current {
246
+ font-size: 1.4rem;
247
+ font-weight: 500;
248
+ color: #1f2937;
249
+ text-align: center;
250
+ line-height: 1.6;
251
+ padding: 0 20px;
252
+ }
253
+
254
+ .utterance-past {
255
+ font-size: 1.2rem;
256
+ color: #6b7280;
257
+ opacity: 0.6;
258
+ text-align: center;
259
+ line-height: 1.5;
260
+ padding: 0 20px;
261
+ }
262
+
263
+ .utterance-final {
264
+ width: 100%;
265
+ display: flex;
266
+ flex-direction: column;
267
+ padding: 12px 0;
268
+ transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
269
+ }
270
+
271
+ .utterance-final.is-doctor {
272
+ align-items: flex-end;
273
+ }
274
+
275
+ .utterance-final.is-patient {
276
+ align-items: flex-start;
277
+ }
278
+
279
+ .speaker-label {
280
+ font-size: 0.75rem;
281
+ font-weight: 500;
282
+ color: #9ca3af;
283
+ margin-bottom: 6px;
284
+ padding: 0 8px;
285
+ text-transform: uppercase;
286
+ letter-spacing: 1px;
287
+ }
288
+
289
+ /* Chat bubbles */
290
+ .bubble-doctor {
291
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
292
+ color: white;
293
+ border-radius: 20px 20px 6px 20px;
294
+ padding: 14px 18px;
295
+ min-width: 120px;
296
+ max-width: min(450px, 75vw);
297
+ word-break: break-word;
298
+ white-space: pre-wrap;
299
+ box-shadow: 0 4px 20px rgba(102, 126, 234, 0.25), 0 2px 10px rgba(118, 75, 162, 0.15);
300
+ font-size: 15px;
301
+ line-height: 1.5;
302
+ font-weight: 400;
303
+ }
304
+
305
+ .bubble-patient {
306
+ background: #ffffff;
307
+ color: #1f2937;
308
+ border: 1px solid rgba(0, 0, 0, 0.08);
309
+ border-radius: 20px 20px 20px 6px;
310
+ padding: 14px 18px;
311
+ min-width: 120px;
312
+ max-width: min(450px, 75vw);
313
+ word-break: break-word;
314
+ white-space: pre-wrap;
315
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08), 0 2px 10px rgba(0, 0, 0, 0.05);
316
+ font-size: 15px;
317
+ line-height: 1.5;
318
+ font-weight: 400;
319
+ }
320
+
321
+ /* Slide up animation */
322
+ .slide-up {
323
+ animation: slideUp 0.5s cubic-bezier(0.4, 0, 0.2, 1);
324
+ }
325
+
326
+ @keyframes slideUp {
327
+ from {
328
+ transform: translateY(30px);
329
+ opacity: 0;
330
+ }
331
+ to {
332
+ transform: translateY(0);
333
+ opacity: 1;
334
+ }
335
+ }
336
+
337
+ /* ==================== Clean Input ==================== */
338
+
339
+ .clean-input .q-field__control {
340
+ background: transparent !important;
341
+ border: none !important;
342
+ border-radius: 0 !important;
343
+ box-shadow: none !important;
344
+ height: 48px !important;
345
+ }
346
+
347
+ .clean-input .q-field__native,
348
+ .clean-input input,
349
+ .clean-input textarea {
350
+ color: #1f2937 !important;
351
+ font-size: 15px !important;
352
+ }
353
+
354
+ .clean-input .q-field__native::placeholder,
355
+ .clean-input input::placeholder,
356
+ .clean-input textarea::placeholder {
357
+ color: #9ca3af !important;
358
+ opacity: 1 !important;
359
+ }
360
+
361
+ .clean-input .q-field__control:before {
362
+ border: none !important;
363
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12) !important;
364
+ transition: border-color 0.3s ease !important;
365
+ }
366
+
367
+ .clean-input .q-field__control:hover:before {
368
+ border-bottom-color: rgba(0, 0, 0, 0.2) !important;
369
+ }
370
+
371
+ .clean-input .q-field__control:after {
372
+ border: none !important;
373
+ border-bottom: 2px solid #667eea !important;
374
+ transform: scaleX(0);
375
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
376
+ }
377
+
378
+ .clean-input.q-field--focused .q-field__control:after {
379
+ transform: scaleX(1);
380
+ }
381
+
382
+ .notes-textarea .q-field__control {
383
+ height: 100px !important;
384
+ }
385
+
386
+ .notes-textarea textarea {
387
+ min-height: 70px !important;
388
+ resize: none !important;
389
+ }
390
+
391
+ /* ==================== Action Button ==================== */
392
+
393
+ .action-button {
394
+ border-radius: 24px !important;
395
+ font-size: 16px !important;
396
+ font-weight: 500 !important;
397
+ letter-spacing: 0.02em !important;
398
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
399
+ min-width: 120px !important;
400
+ text-transform: none !important;
401
+ }
402
+
403
+ .action-button:hover {
404
+ transform: translateY(-2px);
405
+ }
406
+
407
+ .action-button:active {
408
+ transform: translateY(0);
409
+ }
410
+
411
+ .action-button[size="lg"] {
412
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
413
+ box-shadow: 0 8px 32px rgba(102, 126, 234, 0.25), 0 4px 16px rgba(118, 75, 162, 0.15) !important;
414
+ }
415
+
416
+ .action-button[size="lg"]:hover {
417
+ background: linear-gradient(135deg, #7c8ef0 0%, #8a5db0 100%) !important;
418
+ box-shadow: 0 12px 40px rgba(102, 126, 234, 0.35), 0 6px 20px rgba(118, 75, 162, 0.25) !important;
419
+ }
420
+
421
+ /* ==================== Responsive ==================== */
422
+
423
+ @media (max-width: 1400px) {
424
+ .px-6 {
425
+ padding-left: 2.5rem !important;
426
+ padding-right: 2.5rem !important;
427
+ }
428
+ }
429
+
430
+ @media (max-width: 1024px) {
431
+ .px-6 {
432
+ padding-left: 2rem !important;
433
+ padding-right: 2rem !important;
434
+ }
435
+
436
+ .lyrics-container {
437
+ padding: 130px 15px 170px 15px !important;
438
+ }
439
+ }
@@ -0,0 +1,293 @@
1
+ /* ==================== Base Styles ==================== */
2
+
3
+ /* Smooth rendering */
4
+ * {
5
+ -webkit-font-smoothing: antialiased;
6
+ -moz-osx-font-smoothing: grayscale;
7
+ }
8
+
9
+ /* Allow scrolling for register page */
10
+ html, body {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow-y: auto !important;
14
+ min-height: 100vh;
15
+ width: 100vw;
16
+ background: #ffffff;
17
+ }
18
+
19
+ /* ==================== Layout Classes ==================== */
20
+
21
+ .items-center {
22
+ align-items: center;
23
+ }
24
+
25
+ .justify-center {
26
+ justify-content: center;
27
+ }
28
+
29
+ .gap-4 {
30
+ gap: 1rem;
31
+ }
32
+
33
+ .mx-auto {
34
+ margin-left: auto;
35
+ margin-right: auto;
36
+ }
37
+
38
+ .mb-1 {
39
+ margin-bottom: 0.25rem;
40
+ }
41
+
42
+ .mb-3 {
43
+ margin-bottom: 0.75rem;
44
+ }
45
+
46
+ .mb-5 {
47
+ margin-bottom: 1.25rem;
48
+ }
49
+
50
+ .mt-4 {
51
+ margin-top: 1rem;
52
+ }
53
+
54
+ .my-3 {
55
+ margin-top: 0.75rem;
56
+ margin-bottom: 0.75rem;
57
+ }
58
+
59
+ .my-4 {
60
+ margin-top: 1rem;
61
+ margin-bottom: 1rem;
62
+ }
63
+
64
+ .w-full {
65
+ width: 100%;
66
+ }
67
+
68
+ .w-16 {
69
+ width: 4rem;
70
+ }
71
+
72
+ .flex-1 {
73
+ flex: 1;
74
+ }
75
+
76
+ .h-16 {
77
+ height: 4rem;
78
+ }
79
+
80
+ /* ==================== Typography ==================== */
81
+
82
+ .text-xs {
83
+ font-size: 0.75rem;
84
+ line-height: 1rem;
85
+ }
86
+
87
+ .text-sm {
88
+ font-size: 0.875rem;
89
+ line-height: 1.25rem;
90
+ }
91
+
92
+ .text-subtitle2 {
93
+ font-size: 0.875rem;
94
+ line-height: 1.375rem;
95
+ font-weight: 500;
96
+ }
97
+
98
+ .text-h5 {
99
+ font-size: 1.5rem;
100
+ line-height: 2rem;
101
+ }
102
+
103
+ .text-center {
104
+ text-align: center;
105
+ }
106
+
107
+ .font-semibold {
108
+ font-weight: 600;
109
+ }
110
+
111
+ .text-grey-6 {
112
+ color: #757575;
113
+ }
114
+
115
+ .text-grey-7 {
116
+ color: #616161;
117
+ }
118
+
119
+ .text-grey-8 {
120
+ color: #424242;
121
+ }
122
+
123
+ /* ==================== Register Card ==================== */
124
+
125
+ .register-card {
126
+ border-radius: 28px !important;
127
+ background: rgba(255, 255, 255, 0.98) !important;
128
+ backdrop-filter: blur(20px) !important;
129
+ -webkit-backdrop-filter: blur(20px) !important;
130
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.08), 0 8px 24px rgba(0, 0, 0, 0.05), 0 0 1px rgba(0, 0, 0, 0.1) !important;
131
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
132
+ }
133
+
134
+ .register-card:hover {
135
+ box-shadow: 0 24px 70px rgba(0, 0, 0, 0.1), 0 10px 28px rgba(0, 0, 0, 0.06), 0 0 1px rgba(0, 0, 0, 0.1) !important;
136
+ }
137
+
138
+ /* ==================== Background ==================== */
139
+
140
+ .bg-white {
141
+ background: linear-gradient(135deg, #fafafa 0%, #ffffff 100%) !important;
142
+ }
143
+
144
+ /* ==================== Gradient Title ==================== */
145
+
146
+ .gradient-title {
147
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
148
+ background-size: 200% 200%;
149
+ -webkit-background-clip: text;
150
+ -webkit-text-fill-color: transparent;
151
+ background-clip: text;
152
+ font-weight: 700;
153
+ animation: gradient-shift 6s ease infinite;
154
+ }
155
+
156
+ @keyframes gradient-shift {
157
+ 0%, 100% {
158
+ background-position: 0 50%;
159
+ }
160
+ 50% {
161
+ background-position: 100% 50%;
162
+ }
163
+ }
164
+
165
+ /* ==================== Clean Input ==================== */
166
+
167
+ .clean-input .q-field__control {
168
+ background: transparent !important;
169
+ border: none !important;
170
+ border-radius: 0 !important;
171
+ box-shadow: none !important;
172
+ height: 48px !important;
173
+ }
174
+
175
+ .clean-input .q-field__native,
176
+ .clean-input input {
177
+ color: #1f2937 !important;
178
+ font-size: 15px !important;
179
+ font-weight: 400 !important;
180
+ }
181
+
182
+ .clean-input .q-field__native::placeholder,
183
+ .clean-input input::placeholder {
184
+ color: #9ca3af !important;
185
+ opacity: 1 !important;
186
+ }
187
+
188
+ .clean-input .q-field__control:before {
189
+ border: none !important;
190
+ border-bottom: 1px solid rgba(0, 0, 0, 0.12) !important;
191
+ transition: border-color 0.3s ease !important;
192
+ }
193
+
194
+ .clean-input .q-field__control:hover:before {
195
+ border-bottom-color: rgba(0, 0, 0, 0.2) !important;
196
+ }
197
+
198
+ .clean-input .q-field__control:after {
199
+ border: none !important;
200
+ border-bottom: 2px solid #667eea !important;
201
+ transform: scaleX(0);
202
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
203
+ }
204
+
205
+ .clean-input.q-field--focused .q-field__control:after {
206
+ transform: scaleX(1);
207
+ }
208
+
209
+ .clean-input .q-field__append {
210
+ height: 48px !important;
211
+ display: flex !important;
212
+ align-items: center !important;
213
+ justify-content: center !important;
214
+ }
215
+
216
+ .clean-input .q-field__append .q-icon {
217
+ color: #9ca3af !important;
218
+ transition: color 0.2s ease !important;
219
+ }
220
+
221
+ .clean-input .q-field__append .q-icon:hover {
222
+ color: #6b7280 !important;
223
+ }
224
+
225
+ /* ==================== Buttons ==================== */
226
+
227
+ /* Register button (主按钮) */
228
+ .register-button {
229
+ border-radius: 24px !important;
230
+ font-size: 16px !important;
231
+ font-weight: 500 !important;
232
+ letter-spacing: 0.02em !important;
233
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
234
+ box-shadow: 0 4px 16px rgba(102, 126, 234, 0.25), 0 2px 8px rgba(118, 75, 162, 0.15) !important;
235
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
236
+ text-transform: none !important;
237
+ }
238
+
239
+ .register-button:hover {
240
+ transform: translateY(-2px);
241
+ box-shadow: 0 8px 24px rgba(102, 126, 234, 0.35), 0 4px 12px rgba(118, 75, 162, 0.25) !important;
242
+ background: linear-gradient(135deg, #7c8ef0 0%, #8a5db0 100%) !important;
243
+ }
244
+
245
+ .register-button:active {
246
+ transform: translateY(0);
247
+ }
248
+
249
+ /* Back button (次要按钮) */
250
+ .back-button {
251
+ border-radius: 24px !important;
252
+ border: 1px solid rgba(0, 0, 0, 0.08) !important;
253
+ font-size: 16px !important;
254
+ font-weight: 500 !important;
255
+ letter-spacing: 0.02em !important;
256
+ background: rgba(248, 249, 250, 0.6) !important;
257
+ color: #6b7280 !important;
258
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04) !important;
259
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
260
+ text-transform: none !important;
261
+ }
262
+
263
+ .back-button:hover {
264
+ background: rgba(243, 244, 246, 0.8) !important;
265
+ border-color: rgba(0, 0, 0, 0.12) !important;
266
+ color: #4b5563 !important;
267
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
268
+ transform: translateY(-2px);
269
+ }
270
+
271
+ .back-button:active {
272
+ transform: translateY(0);
273
+ }
274
+
275
+ /* ==================== Separator ==================== */
276
+
277
+ .q-separator {
278
+ background-color: rgba(0, 0, 0, 0.08) !important;
279
+ }
280
+
281
+ /* Section separator */
282
+ .my-4 .q-separator {
283
+ opacity: 0.75;
284
+ }
285
+
286
+ .register-logo img,
287
+ .register-logo {
288
+ width: 64px !important;
289
+ height: 64px !important;
290
+ max-width: 100% !important;
291
+ object-fit: contain !important;
292
+ display: block !important;
293
+ }