ani-auto 1.4.3 → 2.0.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.
Files changed (90) hide show
  1. package/anime/LICENSE +21 -0
  2. package/anime/api/index.js +110 -0
  3. package/anime/app.js +79 -0
  4. package/anime/controllers/animeInfoController.js +48 -0
  5. package/anime/controllers/animeListController.js +21 -0
  6. package/anime/controllers/homeController.js +42 -0
  7. package/anime/controllers/playController.js +140 -0
  8. package/anime/controllers/queueController.js +20 -0
  9. package/anime/controllers/testController.js +667 -0
  10. package/anime/index.js +139 -0
  11. package/anime/middleware/cache.js +64 -0
  12. package/anime/middleware/errorHandler.js +33 -0
  13. package/anime/middleware/rateLimiter.js +73 -0
  14. package/anime/models/animeInfoModel.js +193 -0
  15. package/anime/models/animeListModel.js +69 -0
  16. package/anime/models/homeModel.js +33 -0
  17. package/anime/models/playModel.js +528 -0
  18. package/anime/models/queueModel.js +22 -0
  19. package/anime/package.json +27 -0
  20. package/anime/pnpm-lock.yaml +1774 -0
  21. package/anime/readme.md +236 -0
  22. package/anime/routes/animeInfoRoutes.js +9 -0
  23. package/anime/routes/animeListRoutes.js +9 -0
  24. package/anime/routes/homeRoutes.js +10 -0
  25. package/anime/routes/playRoutes.js +11 -0
  26. package/anime/routes/queueRoutes.js +8 -0
  27. package/anime/routes/testRoutes.js +325 -0
  28. package/anime/routes/webhookRoutes.js +23 -0
  29. package/anime/scrapers/animepahe.js +1053 -0
  30. package/anime/test-server.js +10 -0
  31. package/anime/test.sh +275 -0
  32. package/anime/utils/browser.js +172 -0
  33. package/anime/utils/config.js +209 -0
  34. package/anime/utils/dataProcessor.js +172 -0
  35. package/anime/utils/diskCache.js +228 -0
  36. package/anime/utils/flaresolverr.js +361 -0
  37. package/anime/utils/jsParser.js +19 -0
  38. package/anime/utils/redis.js +64 -0
  39. package/anime/utils/requestManager.js +706 -0
  40. package/anime/utils/urlConverter.js +88 -0
  41. package/anime/utils/webhookNotifier.js +190 -0
  42. package/cookiereader.py +291 -0
  43. package/package.json +14 -6
  44. package/src/anilist.js +19 -2
  45. package/src/api/anilist.js +32 -0
  46. package/src/api/anime.js +181 -0
  47. package/src/api/cf-bypass.js +131 -0
  48. package/src/api/config.js +134 -0
  49. package/src/api/daemon.js +62 -0
  50. package/src/api/download.js +98 -0
  51. package/src/api/match.js +58 -0
  52. package/src/api/runs.js +15 -0
  53. package/src/api/update.js +96 -0
  54. package/src/cli.js +18 -2
  55. package/src/config.js +14 -2
  56. package/src/daemon.js +1 -1
  57. package/src/db.js +38 -11
  58. package/src/engine.js +66 -13
  59. package/src/notify.js +82 -7
  60. package/src/scraper.js +2 -2
  61. package/src/server.js +108 -0
  62. package/utils.js +21 -21
  63. package/web/index.html +13 -0
  64. package/web/package-lock.json +1420 -0
  65. package/web/package.json +24 -0
  66. package/web/src/App.vue +200 -0
  67. package/web/src/api/client.js +75 -0
  68. package/web/src/assets/styles/base.css +961 -0
  69. package/web/src/components/UpdateModal.vue +157 -0
  70. package/web/src/components/sidebar/SidebarResizable.vue +170 -0
  71. package/web/src/components/sidebar/sidebarConfig.js +24 -0
  72. package/web/src/main.js +104 -0
  73. package/web/src/router/index.js +44 -0
  74. package/web/src/stores/config.js +27 -0
  75. package/web/src/stores/download.js +107 -0
  76. package/web/src/stores/update.js +73 -0
  77. package/web/src/views/About.vue +42 -0
  78. package/web/src/views/AniListSync.vue +122 -0
  79. package/web/src/views/AnimeDetail.vue +202 -0
  80. package/web/src/views/AnimeList.vue +110 -0
  81. package/web/src/views/CFResult.vue +312 -0
  82. package/web/src/views/DaemonControl.vue +83 -0
  83. package/web/src/views/Dashboard.vue +187 -0
  84. package/web/src/views/DownloadCenter.vue +153 -0
  85. package/web/src/views/MatchFinder.vue +131 -0
  86. package/web/src/views/OAuthCallback.vue +44 -0
  87. package/web/src/views/Onboarding.vue +93 -0
  88. package/web/src/views/RunHistory.vue +122 -0
  89. package/web/src/views/Settings.vue +410 -0
  90. package/web/vite.config.js +23 -0
@@ -0,0 +1,961 @@
1
+ @font-face {
2
+ font-family: 'Departure Mono';
3
+ font-style: normal;
4
+ font-display: swap;
5
+ src: url('https://cdn.jsdelivr.net/npm/@proj-airi/font-departure-mono@0.10.2/dist/files/DepartureMono-Regular.woff2') format('woff2');
6
+ }
7
+
8
+ :root {
9
+ --bg-primary: #000000;
10
+ --bg-surface: #0A0A0A;
11
+ --bg-card: #111111;
12
+ --bg-hover: #1A1A1A;
13
+
14
+ --red-primary: #CC0000;
15
+ --red-hover: #8B0000;
16
+ --red-bright: #FF1A1A;
17
+ --red-subtle: #1A0505;
18
+
19
+ --ink-100: #1A1A1A;
20
+ --ink-300: #333333;
21
+ --ink-500: #666666;
22
+ --ink-700: #999999;
23
+
24
+ --text-primary: #E0E0E0;
25
+ --text-bright: #FFFFFF;
26
+ --text-dim: #666666;
27
+
28
+ --status-done: #00CC66;
29
+ --status-fail: #CC0000;
30
+ --status-pending: #666666;
31
+ --status-downloading: #FF1A1A;
32
+
33
+ --radius: 4px;
34
+ --font-mono: 'Courier New', 'Consolas', monospace;
35
+ --font-logo: 'Departure Mono', 'Courier New', monospace;
36
+ --font-sans: -apple-system, 'Inter', 'Segoe UI', sans-serif;
37
+ }
38
+
39
+ *, *::before, *::after {
40
+ margin: 0;
41
+ padding: 0;
42
+ box-sizing: border-box;
43
+ }
44
+
45
+ html, body {
46
+ height: 100%;
47
+ background: var(--bg-primary);
48
+ color: var(--text-primary);
49
+ font-family: var(--font-sans);
50
+ font-size: 14px;
51
+ line-height: 1.5;
52
+ -webkit-font-smoothing: antialiased;
53
+ }
54
+
55
+ a { color: var(--red-primary); text-decoration: none; }
56
+ a:hover { color: var(--red-bright); }
57
+
58
+ ::selection { background: var(--red-primary); color: #fff; }
59
+ ::-webkit-scrollbar { width: 6px; }
60
+ ::-webkit-scrollbar-track { background: var(--bg-primary); }
61
+ ::-webkit-scrollbar-thumb { background: var(--ink-300); }
62
+
63
+ #app {
64
+ display: flex;
65
+ min-height: 100vh;
66
+ width: 100%;
67
+ }
68
+
69
+ /* ── Resizable Sidebar ── */
70
+
71
+ .sidebar-resizable {
72
+ background: var(--bg-surface);
73
+ border-right: 1px solid var(--ink-100);
74
+ display: flex;
75
+ flex-direction: column;
76
+ position: fixed;
77
+ top: 0;
78
+ left: 0;
79
+ bottom: 0;
80
+ z-index: 10;
81
+ user-select: none;
82
+ overflow: hidden;
83
+ }
84
+
85
+ .sidebar-resizable.collapsed {
86
+ align-items: center;
87
+ }
88
+
89
+ /* Logo */
90
+ .sidebar-logo {
91
+ padding: 20px 16px;
92
+ flex-shrink: 0;
93
+ cursor: default;
94
+ }
95
+
96
+ .sidebar-resizable.collapsed .sidebar-logo {
97
+ padding: 20px 0;
98
+ text-align: center;
99
+ }
100
+
101
+ .slim-logo-text {
102
+ font-family: var(--font-logo);
103
+ font-size: 24px;
104
+ font-weight: 700;
105
+ color: var(--red-primary);
106
+ letter-spacing: 0;
107
+ line-height: 1;
108
+ }
109
+
110
+ .sidebar-logo-brand {
111
+ font-family: var(--font-logo);
112
+ font-size: 16px;
113
+ font-weight: 700;
114
+ color: var(--red-primary);
115
+ letter-spacing: 0.5px;
116
+ display: block;
117
+ line-height: 1.2;
118
+ }
119
+
120
+ .sidebar-logo-tagline {
121
+ font-family: var(--font-mono);
122
+ font-size: 10px;
123
+ color: var(--ink-500);
124
+ letter-spacing: 1px;
125
+ display: block;
126
+ margin-top: 2px;
127
+ }
128
+
129
+ /* Nav */
130
+ .sidebar-nav {
131
+ flex: 1;
132
+ display: flex;
133
+ flex-direction: column;
134
+ padding: 0 8px;
135
+ overflow-y: auto;
136
+ overflow-x: hidden;
137
+ gap: 2px;
138
+ }
139
+
140
+ .sidebar-resizable.collapsed .sidebar-nav {
141
+ align-items: center;
142
+ padding: 0;
143
+ }
144
+
145
+ .sidebar-nav-item {
146
+ display: flex;
147
+ align-items: center;
148
+ gap: 10px;
149
+ padding: 6px 8px;
150
+ min-height: 36px;
151
+ border-radius: 8px;
152
+ color: var(--ink-500);
153
+ text-decoration: none;
154
+ transition: background 0.1s, color 0.1s;
155
+ position: relative;
156
+ flex-shrink: 0;
157
+ }
158
+
159
+ .sidebar-nav-item:hover {
160
+ background: var(--bg-hover);
161
+ }
162
+
163
+ .sidebar-nav-item.active {
164
+ background: var(--red-subtle);
165
+ color: var(--red-primary);
166
+ }
167
+
168
+ .sidebar-resizable.collapsed .sidebar-nav-item {
169
+ width: 36px;
170
+ height: 36px;
171
+ padding: 0;
172
+ justify-content: center;
173
+ }
174
+
175
+ /* Nav icon */
176
+ .sidebar-nav-icon {
177
+ width: 20px;
178
+ height: 20px;
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ flex-shrink: 0;
183
+ position: relative;
184
+ }
185
+
186
+ /* Nav label */
187
+ .sidebar-nav-label {
188
+ font-size: 13px;
189
+ font-weight: 600;
190
+ color: var(--text-dim);
191
+ white-space: nowrap;
192
+ overflow: hidden;
193
+ text-overflow: ellipsis;
194
+ flex: 1;
195
+ }
196
+
197
+ .sidebar-nav-item.active .sidebar-nav-label {
198
+ color: var(--red-primary);
199
+ }
200
+
201
+ .sidebar-nav-item:hover .sidebar-nav-label {
202
+ color: var(--text-primary);
203
+ }
204
+
205
+ /* Nav count badge */
206
+ .sidebar-nav-count {
207
+ font-family: var(--font-mono);
208
+ font-size: 10px;
209
+ color: var(--ink-500);
210
+ background: var(--ink-100);
211
+ padding: 1px 6px;
212
+ border-radius: 10px;
213
+ flex-shrink: 0;
214
+ }
215
+
216
+ .sidebar-nav-item.active .sidebar-nav-count {
217
+ background: var(--red-subtle);
218
+ color: var(--red-primary);
219
+ }
220
+
221
+ /* Slim badge (dot) — for collapsed state */
222
+ .slim-badge {
223
+ position: absolute;
224
+ top: -4px;
225
+ right: -4px;
226
+ width: 8px;
227
+ height: 8px;
228
+ border-radius: 50%;
229
+ background: var(--red-primary);
230
+ }
231
+
232
+ /* Tooltip — for collapsed state */
233
+ .slim-tooltip {
234
+ position: absolute;
235
+ left: calc(100% + 8px);
236
+ top: 50%;
237
+ transform: translateY(-50%);
238
+ background: var(--bg-surface);
239
+ color: var(--text-primary);
240
+ font-size: 13px;
241
+ font-weight: 600;
242
+ padding: 6px 10px;
243
+ border-radius: 6px;
244
+ white-space: nowrap;
245
+ pointer-events: none;
246
+ opacity: 0;
247
+ transition: opacity 0.1s;
248
+ z-index: 30;
249
+ border: 1px solid var(--ink-100);
250
+ }
251
+
252
+ .sidebar-nav-item:hover .slim-tooltip {
253
+ opacity: 1;
254
+ }
255
+
256
+ /* Footer */
257
+ .sidebar-footer {
258
+ border-top: 1px solid var(--ink-100);
259
+ padding: 8px 8px 12px;
260
+ display: flex;
261
+ flex-direction: column;
262
+ gap: 2px;
263
+ flex-shrink: 0;
264
+ }
265
+
266
+ .sidebar-resizable.collapsed .sidebar-footer {
267
+ align-items: center;
268
+ padding: 8px 0;
269
+ }
270
+
271
+ /* User section in footer */
272
+ .sidebar-user {
273
+ display: flex;
274
+ align-items: center;
275
+ gap: 8px;
276
+ padding: 8px 8px 0;
277
+ margin-top: 4px;
278
+ }
279
+
280
+ .sidebar-resizable.collapsed .sidebar-user {
281
+ padding: 4px 0 0;
282
+ gap: 0;
283
+ justify-content: center;
284
+ }
285
+
286
+ .sidebar-avatar {
287
+ width: 28px;
288
+ height: 28px;
289
+ border-radius: 50%;
290
+ background: var(--ink-300);
291
+ display: flex;
292
+ align-items: center;
293
+ justify-content: center;
294
+ font-size: 12px;
295
+ font-weight: 600;
296
+ color: var(--text-primary);
297
+ object-fit: cover;
298
+ flex-shrink: 0;
299
+ }
300
+
301
+ .sidebar-user-info {
302
+ display: flex;
303
+ flex-direction: column;
304
+ gap: 1px;
305
+ min-width: 0;
306
+ flex: 1;
307
+ }
308
+
309
+ .sidebar-user-name {
310
+ font-size: 12px;
311
+ color: var(--text-primary);
312
+ white-space: nowrap;
313
+ overflow: hidden;
314
+ text-overflow: ellipsis;
315
+ }
316
+
317
+ .sidebar-user-version {
318
+ font-size: 10px;
319
+ color: var(--ink-500);
320
+ font-family: var(--font-mono);
321
+ }
322
+
323
+ /* Resize handle */
324
+ .sidebar-resize-area {
325
+ position: absolute;
326
+ right: 0;
327
+ top: 0;
328
+ bottom: 0;
329
+ width: 5px;
330
+ cursor: col-resize;
331
+ z-index: 5;
332
+ transition: background 0.15s;
333
+ }
334
+
335
+ .sidebar-resize-area:hover,
336
+ .sidebar-resize-area:active {
337
+ background: var(--red-primary);
338
+ opacity: 0.4;
339
+ }
340
+
341
+ /* ── Layout ── */
342
+
343
+ .main-column {
344
+ flex: 1;
345
+ display: flex;
346
+ flex-direction: column;
347
+ min-width: 0;
348
+ width: 100%;
349
+ margin-left: 200px;
350
+ }
351
+
352
+ .top-bar {
353
+ height: 48px;
354
+ flex-shrink: 0;
355
+ display: flex;
356
+ align-items: center;
357
+ justify-content: space-between;
358
+ padding: 0 32px;
359
+ border-bottom: 1px solid var(--ink-100);
360
+ }
361
+
362
+ .top-bar-left {
363
+ display: flex;
364
+ align-items: center;
365
+ gap: 8px;
366
+ }
367
+
368
+ .top-bar-label {
369
+ font-size: 13px;
370
+ color: var(--text-dim);
371
+ letter-spacing: 0.5px;
372
+ }
373
+
374
+ .top-bar-right {
375
+ display: flex;
376
+ align-items: center;
377
+ }
378
+
379
+ .top-bar-time {
380
+ font-size: 11px;
381
+ font-family: var(--font-mono);
382
+ color: var(--ink-500);
383
+ padding: 2px 8px;
384
+ border: 1px solid var(--ink-300);
385
+ border-radius: 4px;
386
+ }
387
+
388
+ .update-pill {
389
+ font-size: 11px;
390
+ font-family: var(--font-mono);
391
+ color: var(--red-primary);
392
+ padding: 2px 8px;
393
+ border: 1px solid var(--red-primary);
394
+ border-radius: 4px;
395
+ cursor: pointer;
396
+ margin-right: 8px;
397
+ transition: background 0.1s, color 0.1s;
398
+ }
399
+
400
+ .update-pill:hover {
401
+ background: var(--red-subtle);
402
+ color: var(--red-bright);
403
+ }
404
+
405
+ .main {
406
+ flex: 1;
407
+ overflow-y: auto;
408
+ padding: 24px 32px;
409
+ }
410
+
411
+ /* ── Page Header ── */
412
+
413
+ .page-header-actions {
414
+ display: flex;
415
+ gap: 8px;
416
+ flex-shrink: 0;
417
+ }
418
+
419
+ .page-header {
420
+ display: flex;
421
+ justify-content: space-between;
422
+ align-items: flex-start;
423
+ gap: 16px;
424
+ flex-wrap: wrap;
425
+ margin-bottom: 28px;
426
+ }
427
+
428
+ .page-header h2 {
429
+ font-size: 20px;
430
+ font-weight: 600;
431
+ color: var(--text-bright);
432
+ letter-spacing: 0.5px;
433
+ }
434
+
435
+ .page-header .subtitle {
436
+ color: var(--ink-500);
437
+ font-size: 13px;
438
+ margin-top: 4px;
439
+ }
440
+
441
+ /* ── Stats ── */
442
+
443
+ .stat-row {
444
+ display: grid;
445
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
446
+ gap: 10px;
447
+ margin-bottom: 20px;
448
+ }
449
+
450
+ .stat-inner {
451
+ text-align: center;
452
+ padding: 8px 0;
453
+ }
454
+
455
+ .stat-value {
456
+ font-family: var(--font-mono);
457
+ font-size: 28px;
458
+ font-weight: 700;
459
+ color: var(--text-bright);
460
+ }
461
+
462
+ .stat-label {
463
+ font-size: 11px;
464
+ color: var(--ink-500);
465
+ text-transform: uppercase;
466
+ letter-spacing: 1px;
467
+ margin-top: 4px;
468
+ }
469
+
470
+ /* ── Anime Grid ── */
471
+
472
+ .anime-grid {
473
+ display: grid;
474
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
475
+ gap: 12px;
476
+ }
477
+
478
+ .anime-card {
479
+ background: var(--bg-card);
480
+ border: 1px solid var(--ink-100);
481
+ border-radius: var(--radius);
482
+ padding: 12px;
483
+ cursor: pointer;
484
+ transition: border-color 0.15s, background 0.15s;
485
+ display: flex;
486
+ gap: 12px;
487
+ }
488
+
489
+ .anime-card:hover {
490
+ border-color: var(--ink-300);
491
+ background: var(--bg-hover);
492
+ }
493
+
494
+ .anime-card .anime-poster {
495
+ width: 50px;
496
+ min-width: 50px;
497
+ height: 75px;
498
+ object-fit: cover;
499
+ border-radius: var(--radius);
500
+ background: var(--bg-hover);
501
+ }
502
+
503
+ .anime-card .anime-info {
504
+ flex: 1;
505
+ min-width: 0;
506
+ }
507
+
508
+ .anime-card .anime-title {
509
+ font-size: 13px;
510
+ font-weight: 600;
511
+ color: var(--text-bright);
512
+ margin-bottom: 4px;
513
+ display: -webkit-box;
514
+ -webkit-line-clamp: 2;
515
+ -webkit-box-orient: vertical;
516
+ overflow: hidden;
517
+ }
518
+
519
+ .anime-card .anime-meta {
520
+ font-size: 10px;
521
+ color: var(--ink-500);
522
+ margin-bottom: 6px;
523
+ }
524
+
525
+ .anime-card .anime-progress {
526
+ height: 3px;
527
+ background: var(--ink-100);
528
+ border-radius: var(--radius);
529
+ overflow: hidden;
530
+ margin-bottom: 6px;
531
+ }
532
+
533
+ .anime-card .anime-progress .bar {
534
+ height: 100%;
535
+ background: var(--red-primary);
536
+ border-radius: var(--radius);
537
+ transition: width 0.3s;
538
+ }
539
+
540
+ .anime-card .anime-stats {
541
+ display: flex;
542
+ gap: 10px;
543
+ font-size: 10px;
544
+ font-family: var(--font-mono);
545
+ }
546
+
547
+ .anime-card .anime-stats .done { color: var(--status-done); }
548
+ .anime-card .anime-stats .failed { color: var(--status-fail); }
549
+ .anime-card .anime-stats .pending { color: var(--status-pending); }
550
+
551
+ /* ── List Group ── */
552
+
553
+ .list-group {
554
+ border: 1px solid var(--ink-100);
555
+ border-radius: var(--radius);
556
+ overflow: hidden;
557
+ }
558
+
559
+ .anime-card-row {
560
+ background: var(--bg-card);
561
+ padding: 12px 16px;
562
+ cursor: pointer;
563
+ transition: background 0.15s;
564
+ display: flex;
565
+ align-items: center;
566
+ gap: 14px;
567
+ border-bottom: 1px solid var(--ink-100);
568
+ }
569
+
570
+ .anime-card-row:last-child {
571
+ border-bottom: none;
572
+ }
573
+
574
+ .anime-card-row:hover {
575
+ background: var(--bg-hover);
576
+ }
577
+
578
+ .anime-card-row .anime-poster {
579
+ width: 40px;
580
+ min-width: 40px;
581
+ height: 56px;
582
+ object-fit: cover;
583
+ border-radius: var(--radius);
584
+ background: var(--bg-hover);
585
+ }
586
+
587
+ .anime-card-row .anime-info {
588
+ flex: 1;
589
+ min-width: 0;
590
+ }
591
+
592
+ .anime-card-row .anime-title {
593
+ font-size: 13px;
594
+ font-weight: 600;
595
+ color: var(--text-bright);
596
+ margin-bottom: 2px;
597
+ }
598
+
599
+ .anime-card-row .anime-meta {
600
+ font-size: 11px;
601
+ color: var(--ink-500);
602
+ }
603
+
604
+ /* ── Forms ── */
605
+
606
+ .form-group {
607
+ margin-bottom: 18px;
608
+ }
609
+
610
+ .form-group label {
611
+ display: block;
612
+ font-size: 12px;
613
+ color: var(--ink-700);
614
+ text-transform: uppercase;
615
+ letter-spacing: 0.5px;
616
+ margin-bottom: 6px;
617
+ }
618
+
619
+ .form-row {
620
+ display: grid;
621
+ grid-template-columns: 1fr 1fr;
622
+ gap: 16px;
623
+ }
624
+
625
+ .form-section {
626
+ margin-bottom: 32px;
627
+ }
628
+
629
+ .form-section h3 {
630
+ font-size: 14px;
631
+ color: var(--text-bright);
632
+ margin-bottom: 16px;
633
+ padding-bottom: 8px;
634
+ border-bottom: 1px solid var(--ink-100);
635
+ }
636
+
637
+ .checkbox-group {
638
+ display: flex;
639
+ gap: 16px;
640
+ margin-top: 6px;
641
+ flex-wrap: wrap;
642
+ }
643
+
644
+ .checkbox-item {
645
+ display: flex;
646
+ align-items: center;
647
+ gap: 6px;
648
+ font-size: 13px;
649
+ cursor: pointer;
650
+ }
651
+
652
+ .form-field-row {
653
+ display: flex;
654
+ gap: 10px;
655
+ align-items: center;
656
+ }
657
+
658
+ .form-hint {
659
+ font-size: 11px;
660
+ color: var(--ink-500);
661
+ margin-top: 6px;
662
+ line-height: 1.5;
663
+ }
664
+
665
+ .version-display {
666
+ font-family: var(--font-mono);
667
+ font-size: 14px;
668
+ color: var(--text-primary);
669
+ font-weight: 600;
670
+ }
671
+
672
+ .update-result {
673
+ display: flex;
674
+ align-items: center;
675
+ gap: 12px;
676
+ margin-top: 16px;
677
+ padding-top: 12px;
678
+ border-top: 1px solid var(--ink-100);
679
+ }
680
+
681
+ .update-result-text {
682
+ font-size: 13px;
683
+ color: var(--red-primary);
684
+ font-weight: 600;
685
+ }
686
+
687
+ .update-result-ok {
688
+ color: var(--status-done);
689
+ }
690
+
691
+ /* ── Toolbars ── */
692
+
693
+ .anilist-toolbar,
694
+ .anime-list-toolbar {
695
+ display: flex;
696
+ gap: 10px;
697
+ margin-bottom: 16px;
698
+ flex-wrap: wrap;
699
+ align-items: center;
700
+ }
701
+
702
+ /* ── Settings ── */
703
+
704
+ .settings-actions {
705
+ display: flex;
706
+ gap: 10px;
707
+ margin-top: 24px;
708
+ padding-top: 16px;
709
+ border-top: 1px solid var(--ink-100);
710
+ align-items: center;
711
+ }
712
+
713
+ .saved-msg {
714
+ color: var(--status-done);
715
+ font-size: 13px;
716
+ }
717
+
718
+ /* ── Anime Detail ── */
719
+
720
+ .anime-detail-layout {
721
+ display: flex;
722
+ gap: 20px;
723
+ align-items: start;
724
+ }
725
+
726
+ .anime-detail-poster {
727
+ width: 120px;
728
+ min-width: 120px;
729
+ border-radius: var(--radius);
730
+ background: var(--bg-hover);
731
+ }
732
+
733
+ /* ── Empty Content ── */
734
+
735
+ .empty-content {
736
+ text-align: center;
737
+ padding: 30px 20px;
738
+ color: var(--ink-500);
739
+ }
740
+
741
+ .empty-content h3 {
742
+ font-size: 16px;
743
+ color: var(--ink-700);
744
+ margin-bottom: 8px;
745
+ }
746
+
747
+ /* ── Onboarding ── */
748
+
749
+ .onboarding {
750
+ display: flex;
751
+ align-items: center;
752
+ justify-content: center;
753
+ height: 100vh;
754
+ background: var(--bg-primary);
755
+ margin-left: 0;
756
+ width: 100%;
757
+ }
758
+
759
+ .onboarding-box {
760
+ text-align: center;
761
+ max-width: 440px;
762
+ padding: 40px;
763
+ }
764
+
765
+ .onboarding-box .logo {
766
+ font-family: var(--font-logo);
767
+ font-size: 36px;
768
+ font-weight: 700;
769
+ color: var(--red-primary);
770
+ letter-spacing: 6px;
771
+ margin-bottom: 8px;
772
+ }
773
+
774
+ .onboarding-box .logo-sub {
775
+ font-size: 11px;
776
+ color: var(--ink-500);
777
+ letter-spacing: 2px;
778
+ text-transform: uppercase;
779
+ margin-bottom: 32px;
780
+ }
781
+
782
+ .onboarding-box h2 {
783
+ color: var(--text-bright);
784
+ font-size: 18px;
785
+ margin-bottom: 8px;
786
+ }
787
+
788
+ .onboarding-box p {
789
+ color: var(--ink-700);
790
+ font-size: 13px;
791
+ margin-bottom: 28px;
792
+ line-height: 1.7;
793
+ }
794
+
795
+ .onboarding-box .btn-group {
796
+ display: flex;
797
+ flex-direction: column;
798
+ gap: 10px;
799
+ align-items: center;
800
+ }
801
+
802
+ /* ── Mobile Hamburger ── */
803
+
804
+ .hamburger {
805
+ display: none;
806
+ background: none;
807
+ border: none;
808
+ color: var(--ink-500);
809
+ cursor: pointer;
810
+ padding: 4px;
811
+ margin-right: 8px;
812
+ line-height: 0;
813
+ }
814
+
815
+ .hamburger:hover {
816
+ color: var(--text-primary);
817
+ }
818
+
819
+ /* ── Sidebar Overlay ── */
820
+
821
+ .sidebar-overlay {
822
+ display: none;
823
+ }
824
+
825
+ /* ── Mobile Breakpoint ── */
826
+
827
+ @media (max-width: 767px) {
828
+ .hamburger {
829
+ display: block;
830
+ }
831
+
832
+ .sidebar-resizable {
833
+ width: 260px !important;
834
+ transform: translateX(-100%);
835
+ transition: transform 0.2s ease;
836
+ z-index: 20;
837
+ padding: 0 12px;
838
+ }
839
+ .sidebar-resizable.mobile-open {
840
+ transform: translateX(0);
841
+ }
842
+
843
+ .sidebar-resizable.collapsed {
844
+ width: 260px !important;
845
+ align-items: stretch;
846
+ }
847
+
848
+ .sidebar-resizable.collapsed .sidebar-logo {
849
+ padding: 20px 16px;
850
+ text-align: left;
851
+ }
852
+
853
+ .sidebar-resizable.collapsed .sidebar-nav {
854
+ align-items: stretch;
855
+ padding: 0 8px;
856
+ }
857
+
858
+ .sidebar-resizable.collapsed .sidebar-nav-item {
859
+ width: 100%;
860
+ height: auto;
861
+ padding: 6px 8px;
862
+ justify-content: flex-start;
863
+ }
864
+
865
+ .sidebar-resizable.collapsed .sidebar-nav-item .slim-tooltip {
866
+ display: inline;
867
+ }
868
+
869
+ .sidebar-resizable.collapsed .sidebar-footer {
870
+ display: flex;
871
+ align-items: stretch;
872
+ padding: 8px 12px;
873
+ }
874
+
875
+ .sidebar-resizable.collapsed .sidebar-footer .sidebar-nav-item {
876
+ width: 100%;
877
+ }
878
+
879
+ .sidebar-resizable.collapsed .sidebar-user {
880
+ padding: 8px 8px 0;
881
+ gap: 8px;
882
+ justify-content: flex-start;
883
+ }
884
+
885
+ .sidebar-resizable .slim-tooltip {
886
+ position: static;
887
+ transform: none;
888
+ opacity: 1;
889
+ background: none;
890
+ border: none;
891
+ padding: 0;
892
+ font-size: 13px;
893
+ font-weight: 600;
894
+ color: var(--text-dim);
895
+ pointer-events: auto;
896
+ }
897
+
898
+ .sidebar-resizable .sidebar-nav {
899
+ align-items: stretch;
900
+ padding: 0 8px;
901
+ }
902
+
903
+ .sidebar-resizable .sidebar-footer {
904
+ display: flex;
905
+ flex-direction: column;
906
+ gap: 2px;
907
+ padding: 8px 12px;
908
+ }
909
+
910
+ .sidebar-resizable .sidebar-footer .sidebar-nav-item {
911
+ width: 100%;
912
+ }
913
+
914
+ .sidebar-resizable .sidebar-user {
915
+ margin-left: 4px;
916
+ flex: 1;
917
+ min-width: 0;
918
+ }
919
+
920
+ .sidebar-resizable .sidebar-user-info {
921
+ display: flex;
922
+ }
923
+
924
+ .sidebar-resizable .sidebar-logo {
925
+ padding: 20px 16px;
926
+ }
927
+
928
+ .sidebar-resizable .sidebar-resize-area {
929
+ display: none;
930
+ }
931
+
932
+ .sidebar-overlay {
933
+ display: block;
934
+ position: fixed;
935
+ inset: 0;
936
+ background: rgba(0, 0, 0, 0.5);
937
+ z-index: 15;
938
+ }
939
+
940
+ .main-column {
941
+ margin-left: 0 !important;
942
+ width: 100% !important;
943
+ }
944
+
945
+ .top-bar {
946
+ margin-left: 0 !important;
947
+ width: 100% !important;
948
+ }
949
+
950
+ .top-bar-label {
951
+ font-size: 14px;
952
+ max-width: 60vw;
953
+ overflow: hidden;
954
+ text-overflow: ellipsis;
955
+ white-space: nowrap;
956
+ }
957
+
958
+ .form-row {
959
+ grid-template-columns: 1fr;
960
+ }
961
+ }