html2apk 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.
Files changed (36) hide show
  1. package/README.md +472 -0
  2. package/bin/html2apk-desktop.js +23 -0
  3. package/bin/html2apk.js +19 -0
  4. package/examples/minimal/app.json +27 -0
  5. package/examples/minimal/dist/MeuApp-1.0.0-debug.apk +0 -0
  6. package/examples/minimal/index.html +41 -0
  7. package/html2apk.png +0 -0
  8. package/index.js +3 -0
  9. package/package.json +76 -0
  10. package/src/android/README.md +7 -0
  11. package/src/bridge/install-bridge.js +16 -0
  12. package/src/cli/index.js +163 -0
  13. package/src/cordova/apk-finder.js +45 -0
  14. package/src/cordova/config-xml.js +110 -0
  15. package/src/cordova/project.js +56 -0
  16. package/src/core/build-apk.js +189 -0
  17. package/src/core/config.js +99 -0
  18. package/src/core/defaults.js +37 -0
  19. package/src/core/validation.js +58 -0
  20. package/src/desktop/main.js +522 -0
  21. package/src/desktop/preload.js +30 -0
  22. package/src/desktop/renderer/index.html +323 -0
  23. package/src/desktop/renderer/renderer.js +1074 -0
  24. package/src/desktop/renderer/styles.css +1208 -0
  25. package/src/index.js +12 -0
  26. package/src/runtime-manager/doctor.js +164 -0
  27. package/src/runtime-manager/index.js +190 -0
  28. package/src/templates/cordova-plugin-html2apk-bridge/package.json +16 -0
  29. package/src/templates/cordova-plugin-html2apk-bridge/plugin.xml +39 -0
  30. package/src/templates/cordova-plugin-html2apk-bridge/src/android/BootReceiver.java +20 -0
  31. package/src/templates/cordova-plugin-html2apk-bridge/src/android/Html2ApkBridge.java +375 -0
  32. package/src/templates/cordova-plugin-html2apk-bridge/src/android/NotificationReceiver.java +112 -0
  33. package/src/templates/cordova-plugin-html2apk-bridge/src/android/NotificationStore.java +91 -0
  34. package/src/templates/cordova-plugin-html2apk-bridge/www/html2apk-bridge.js +129 -0
  35. package/src/utils/command-runner.js +124 -0
  36. package/src/utils/fs-extra.js +111 -0
@@ -0,0 +1,1208 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --log-bar-height: 162px;
4
+ --visible-log-height: 0px;
5
+ --bg: #f7faff;
6
+ --panel: #ffffff;
7
+ --panel-soft: #eef5ff;
8
+ --text: #172233;
9
+ --muted: #667386;
10
+ --line: #d9e2ef;
11
+ --blue: #126fff;
12
+ --blue-soft: #dceaff;
13
+ --green: #1f9d66;
14
+ --amber: #bc7a12;
15
+ --red: #cf3f4b;
16
+ --shadow: 0 24px 70px rgba(49, 86, 130, 0.16);
17
+ }
18
+
19
+ [data-theme="dark"] {
20
+ color-scheme: dark;
21
+ --bg: #10141b;
22
+ --panel: #161d27;
23
+ --panel-soft: #1d2a3a;
24
+ --text: #edf4ff;
25
+ --muted: #9baabd;
26
+ --line: #293547;
27
+ --blue: #62a0ff;
28
+ --blue-soft: #183456;
29
+ --green: #43c985;
30
+ --amber: #e7ad4c;
31
+ --red: #ff6e7b;
32
+ --shadow: 0 24px 70px rgba(0, 0, 0, 0.36);
33
+ }
34
+
35
+ * {
36
+ box-sizing: border-box;
37
+ }
38
+
39
+ body {
40
+ margin: 0;
41
+ min-height: 100vh;
42
+ overflow: hidden;
43
+ background: var(--bg);
44
+ color: var(--text);
45
+ font-family: Inter, "Segoe UI", Arial, sans-serif;
46
+ letter-spacing: 0;
47
+ }
48
+
49
+ body.logs-visible {
50
+ --visible-log-height: var(--log-bar-height);
51
+ }
52
+
53
+ button,
54
+ input,
55
+ select {
56
+ font: inherit;
57
+ }
58
+
59
+ button {
60
+ cursor: pointer;
61
+ }
62
+
63
+ .drag-region {
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ right: 128px;
68
+ height: 34px;
69
+ z-index: 12;
70
+ -webkit-app-region: drag;
71
+ }
72
+
73
+ .window-controls {
74
+ position: fixed;
75
+ top: 10px;
76
+ right: 12px;
77
+ z-index: 18;
78
+ display: inline-flex;
79
+ gap: 6px;
80
+ -webkit-app-region: no-drag;
81
+ }
82
+
83
+ .window-controls button {
84
+ width: 34px;
85
+ height: 30px;
86
+ border: 1px solid color-mix(in srgb, var(--line) 82%, transparent);
87
+ border-radius: 8px;
88
+ background: color-mix(in srgb, var(--panel) 82%, transparent);
89
+ color: var(--muted);
90
+ font-size: 12px;
91
+ font-weight: 900;
92
+ line-height: 1;
93
+ box-shadow: 0 10px 28px rgba(49, 86, 130, 0.08);
94
+ transition: background 160ms ease, color 160ms ease, transform 160ms ease;
95
+ }
96
+
97
+ .window-controls button:hover {
98
+ background: var(--blue-soft);
99
+ color: var(--blue);
100
+ transform: translateY(-1px);
101
+ }
102
+
103
+ .window-controls .close-control:hover {
104
+ background: var(--red);
105
+ border-color: var(--red);
106
+ color: #ffffff;
107
+ }
108
+
109
+ .app-shell {
110
+ display: grid;
111
+ grid-template-columns: 292px minmax(0, 1fr);
112
+ height: calc(100vh - 34px - var(--visible-log-height));
113
+ transition: height 220ms ease;
114
+ animation: shell-in 620ms cubic-bezier(.2, .8, .2, 1) both;
115
+ }
116
+
117
+ .sidebar {
118
+ border-right: 1px solid var(--line);
119
+ background: color-mix(in srgb, var(--panel) 88%, var(--panel-soft));
120
+ padding: 56px 12px 22px;
121
+ display: flex;
122
+ flex-direction: column;
123
+ }
124
+
125
+ .brand {
126
+ display: flex;
127
+ align-items: center;
128
+ gap: 12px;
129
+ padding: 0 22px 42px;
130
+ }
131
+
132
+ .brand-icon,
133
+ .language-icon,
134
+ .boot-icon {
135
+ width: 52px;
136
+ height: 52px;
137
+ object-fit: cover;
138
+ border-radius: 12px;
139
+ box-shadow: 0 12px 30px rgba(18, 111, 255, 0.25);
140
+ }
141
+
142
+ .brand strong {
143
+ display: block;
144
+ font-size: 28px;
145
+ line-height: 1;
146
+ }
147
+
148
+ .brand strong span {
149
+ color: var(--blue);
150
+ }
151
+
152
+ .brand small {
153
+ display: block;
154
+ margin-top: 6px;
155
+ color: var(--muted);
156
+ }
157
+
158
+ .nav-list {
159
+ display: grid;
160
+ gap: 7px;
161
+ }
162
+
163
+ .nav-item,
164
+ .theme-row {
165
+ border: 0;
166
+ min-height: 56px;
167
+ border-radius: 8px;
168
+ padding: 0 20px;
169
+ display: flex;
170
+ align-items: center;
171
+ gap: 16px;
172
+ background: transparent;
173
+ color: var(--muted);
174
+ text-align: left;
175
+ transition: background 180ms ease, color 180ms ease, transform 180ms ease;
176
+ }
177
+
178
+ .nav-item:hover,
179
+ .theme-row:hover {
180
+ background: var(--panel-soft);
181
+ color: var(--text);
182
+ transform: translateX(2px);
183
+ }
184
+
185
+ .nav-item.active {
186
+ background: var(--blue-soft);
187
+ color: var(--blue);
188
+ box-shadow: inset 4px 0 0 var(--blue);
189
+ }
190
+
191
+ .nav-icon {
192
+ width: 24px;
193
+ height: 24px;
194
+ border: 1px solid currentColor;
195
+ border-radius: 7px;
196
+ display: inline-flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ font-weight: 800;
200
+ font-size: 12px;
201
+ flex: 0 0 auto;
202
+ }
203
+
204
+ .sidebar-bottom {
205
+ margin-top: auto;
206
+ display: grid;
207
+ gap: 7px;
208
+ }
209
+
210
+ .theme-row strong {
211
+ margin-left: auto;
212
+ color: var(--blue);
213
+ }
214
+
215
+ .main {
216
+ min-width: 0;
217
+ overflow: auto;
218
+ padding: 78px 8vw 34px;
219
+ }
220
+
221
+ .view {
222
+ display: none;
223
+ animation: view-in 260ms ease both;
224
+ }
225
+
226
+ .view.active {
227
+ display: block;
228
+ }
229
+
230
+ .view-header {
231
+ display: flex;
232
+ align-items: center;
233
+ justify-content: space-between;
234
+ gap: 24px;
235
+ margin-bottom: 28px;
236
+ }
237
+
238
+ .view-header.compact {
239
+ margin-bottom: 22px;
240
+ }
241
+
242
+ .eyebrow {
243
+ margin: 0 0 9px;
244
+ color: var(--blue);
245
+ font-size: 13px;
246
+ font-weight: 800;
247
+ text-transform: uppercase;
248
+ letter-spacing: .08em;
249
+ }
250
+
251
+ h1,
252
+ h2,
253
+ p {
254
+ margin-top: 0;
255
+ }
256
+
257
+ h1 {
258
+ margin-bottom: 0;
259
+ font-size: clamp(30px, 4vw, 48px);
260
+ line-height: 1.08;
261
+ }
262
+
263
+ h2 {
264
+ font-size: 28px;
265
+ line-height: 1.15;
266
+ }
267
+
268
+ .drop-zone {
269
+ min-height: 520px;
270
+ border: 2px dashed color-mix(in srgb, var(--blue) 55%, transparent);
271
+ border-radius: 10px;
272
+ background: color-mix(in srgb, var(--panel) 80%, transparent);
273
+ display: flex;
274
+ flex-direction: column;
275
+ align-items: center;
276
+ justify-content: center;
277
+ text-align: center;
278
+ padding: 44px;
279
+ transition: border-color 180ms ease, background 180ms ease, transform 180ms ease;
280
+ }
281
+
282
+ .drop-zone.dragging {
283
+ border-color: var(--blue);
284
+ background: var(--blue-soft);
285
+ transform: scale(1.01);
286
+ }
287
+
288
+ .folder-illustration {
289
+ width: 168px;
290
+ height: 132px;
291
+ position: relative;
292
+ margin-bottom: 28px;
293
+ animation: float 2600ms ease-in-out infinite;
294
+ }
295
+
296
+ .folder-tab {
297
+ position: absolute;
298
+ left: 24px;
299
+ top: 6px;
300
+ width: 66px;
301
+ height: 34px;
302
+ border-radius: 10px 10px 4px 4px;
303
+ background: color-mix(in srgb, var(--blue) 56%, #ffffff);
304
+ }
305
+
306
+ .folder-body {
307
+ position: absolute;
308
+ left: 16px;
309
+ right: 16px;
310
+ top: 28px;
311
+ height: 84px;
312
+ border-radius: 10px;
313
+ background: linear-gradient(180deg, color-mix(in srgb, var(--blue) 42%, #ffffff), color-mix(in srgb, var(--blue) 16%, #ffffff));
314
+ box-shadow: inset 0 0 0 1px rgba(18, 111, 255, 0.18), var(--shadow);
315
+ }
316
+
317
+ .upload-mark {
318
+ position: absolute;
319
+ left: 50%;
320
+ bottom: 0;
321
+ width: 84px;
322
+ height: 54px;
323
+ transform: translateX(-50%);
324
+ border: 2px dashed var(--blue);
325
+ border-radius: 10px;
326
+ }
327
+
328
+ .upload-mark::before,
329
+ .upload-mark::after {
330
+ content: "";
331
+ position: absolute;
332
+ background: var(--blue);
333
+ }
334
+
335
+ .upload-mark::before {
336
+ width: 6px;
337
+ height: 30px;
338
+ left: 50%;
339
+ top: 12px;
340
+ transform: translateX(-50%);
341
+ border-radius: 999px;
342
+ }
343
+
344
+ .upload-mark::after {
345
+ width: 22px;
346
+ height: 22px;
347
+ left: 50%;
348
+ top: 9px;
349
+ border-left: 6px solid var(--blue);
350
+ border-top: 6px solid var(--blue);
351
+ background: transparent;
352
+ transform: translateX(-50%) rotate(45deg);
353
+ border-radius: 4px 0 0 0;
354
+ }
355
+
356
+ .drop-zone h2 {
357
+ max-width: 640px;
358
+ margin-bottom: 12px;
359
+ }
360
+
361
+ .drop-zone p {
362
+ color: var(--muted);
363
+ max-width: 540px;
364
+ font-size: 18px;
365
+ }
366
+
367
+ .info-pill {
368
+ margin-top: 14px;
369
+ display: inline-flex;
370
+ align-items: center;
371
+ min-height: 44px;
372
+ padding: 0 18px;
373
+ border-radius: 8px;
374
+ color: var(--blue);
375
+ background: var(--blue-soft);
376
+ font-weight: 700;
377
+ }
378
+
379
+ .summary-grid,
380
+ .settings-grid,
381
+ .toggle-grid,
382
+ .pipeline,
383
+ .review-grid,
384
+ .help-grid {
385
+ display: grid;
386
+ gap: 16px;
387
+ }
388
+
389
+ .summary-grid {
390
+ grid-template-columns: repeat(3, minmax(0, 1fr));
391
+ margin-top: 22px;
392
+ }
393
+
394
+ .summary-card,
395
+ .step-card,
396
+ .field,
397
+ .toggle-card,
398
+ .preference-row,
399
+ .help-grid article,
400
+ .result-panel {
401
+ border: 1px solid var(--line);
402
+ background: var(--panel);
403
+ border-radius: 8px;
404
+ box-shadow: var(--shadow);
405
+ }
406
+
407
+ .summary-card {
408
+ min-height: 112px;
409
+ padding: 18px;
410
+ }
411
+
412
+ .summary-card span,
413
+ .summary-card small,
414
+ .step-card small {
415
+ color: var(--muted);
416
+ }
417
+
418
+ .summary-card strong {
419
+ display: block;
420
+ margin: 8px 0;
421
+ overflow: hidden;
422
+ text-overflow: ellipsis;
423
+ white-space: nowrap;
424
+ }
425
+
426
+ .action-strip {
427
+ margin-top: 24px;
428
+ display: flex;
429
+ gap: 12px;
430
+ justify-content: flex-end;
431
+ }
432
+
433
+ .primary-action,
434
+ .secondary-action {
435
+ border: 0;
436
+ min-height: 44px;
437
+ border-radius: 8px;
438
+ padding: 0 18px;
439
+ font-weight: 800;
440
+ transition: transform 160ms ease, opacity 160ms ease, background 160ms ease;
441
+ }
442
+
443
+ .primary-action {
444
+ background: var(--blue);
445
+ color: #ffffff;
446
+ }
447
+
448
+ .secondary-action {
449
+ background: var(--blue-soft);
450
+ color: var(--blue);
451
+ }
452
+
453
+ .primary-action:hover,
454
+ .secondary-action:hover {
455
+ transform: translateY(-1px);
456
+ }
457
+
458
+ .primary-action:disabled,
459
+ .secondary-action:disabled {
460
+ cursor: not-allowed;
461
+ opacity: .5;
462
+ transform: none;
463
+ }
464
+
465
+ .settings-grid {
466
+ grid-template-columns: repeat(2, minmax(0, 1fr));
467
+ }
468
+
469
+ .field {
470
+ padding: 16px;
471
+ display: grid;
472
+ gap: 10px;
473
+ }
474
+
475
+ .field span,
476
+ .toggle-card strong,
477
+ .preference-row strong {
478
+ font-weight: 800;
479
+ }
480
+
481
+ .field input,
482
+ .field select {
483
+ height: 46px;
484
+ border: 1px solid var(--line);
485
+ border-radius: 8px;
486
+ padding: 0 12px;
487
+ background: var(--bg);
488
+ color: var(--text);
489
+ outline: none;
490
+ }
491
+
492
+ .icon-field {
493
+ grid-column: span 2;
494
+ }
495
+
496
+ .icon-picker {
497
+ display: grid;
498
+ grid-template-columns: 86px minmax(0, 1fr);
499
+ gap: 14px;
500
+ align-items: center;
501
+ }
502
+
503
+ .icon-picker img {
504
+ width: 72px;
505
+ height: 72px;
506
+ object-fit: cover;
507
+ border-radius: 14px;
508
+ border: 1px solid var(--line);
509
+ background: var(--panel-soft);
510
+ box-shadow: 0 14px 34px rgba(18, 111, 255, 0.18);
511
+ }
512
+
513
+ .icon-picker div {
514
+ display: grid;
515
+ gap: 10px;
516
+ }
517
+
518
+ .validation-panel {
519
+ margin-top: 16px;
520
+ border: 1px solid color-mix(in srgb, var(--red) 42%, var(--line));
521
+ border-radius: 8px;
522
+ background: color-mix(in srgb, var(--red) 10%, var(--panel));
523
+ color: var(--red);
524
+ padding: 14px 16px;
525
+ font-weight: 700;
526
+ }
527
+
528
+ .validation-panel p {
529
+ margin: 0 0 8px;
530
+ }
531
+
532
+ .validation-panel ul {
533
+ margin: 0;
534
+ padding-left: 18px;
535
+ }
536
+
537
+ .field input:focus,
538
+ .field select:focus {
539
+ border-color: var(--blue);
540
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent);
541
+ }
542
+
543
+ .toggle-grid {
544
+ grid-template-columns: repeat(2, minmax(0, 1fr));
545
+ margin-top: 16px;
546
+ }
547
+
548
+ .toggle-card {
549
+ min-height: 96px;
550
+ padding: 18px;
551
+ display: flex;
552
+ gap: 14px;
553
+ align-items: center;
554
+ }
555
+
556
+ .toggle-card input {
557
+ width: 22px;
558
+ height: 22px;
559
+ accent-color: var(--blue);
560
+ }
561
+
562
+ .toggle-card small,
563
+ .preference-row p,
564
+ .help-grid p {
565
+ display: block;
566
+ margin: 6px 0 0;
567
+ color: var(--muted);
568
+ }
569
+
570
+ .preference-row {
571
+ min-height: 112px;
572
+ padding: 20px;
573
+ display: flex;
574
+ align-items: center;
575
+ justify-content: space-between;
576
+ gap: 18px;
577
+ margin-bottom: 16px;
578
+ }
579
+
580
+ .segmented {
581
+ display: inline-flex;
582
+ padding: 4px;
583
+ background: var(--panel-soft);
584
+ border-radius: 8px;
585
+ }
586
+
587
+ .segmented button {
588
+ border: 0;
589
+ width: 58px;
590
+ height: 38px;
591
+ border-radius: 7px;
592
+ background: transparent;
593
+ color: var(--muted);
594
+ font-weight: 800;
595
+ }
596
+
597
+ .segmented button.active {
598
+ background: var(--panel);
599
+ color: var(--blue);
600
+ box-shadow: 0 8px 18px rgba(18, 111, 255, 0.12);
601
+ }
602
+
603
+ .pipeline {
604
+ grid-template-columns: repeat(4, minmax(0, 1fr));
605
+ margin-top: 18px;
606
+ }
607
+
608
+ .progress-panel {
609
+ display: grid;
610
+ grid-template-columns: minmax(180px, 260px) minmax(0, 1fr) 64px;
611
+ gap: 16px;
612
+ align-items: center;
613
+ border: 1px solid var(--line);
614
+ border-radius: 8px;
615
+ background: var(--panel);
616
+ box-shadow: var(--shadow);
617
+ padding: 16px;
618
+ margin-bottom: 18px;
619
+ }
620
+
621
+ .progress-copy span {
622
+ display: block;
623
+ color: var(--muted);
624
+ margin-bottom: 5px;
625
+ }
626
+
627
+ .progress-copy strong,
628
+ .progress-percent {
629
+ color: var(--text);
630
+ }
631
+
632
+ .progress-track {
633
+ position: relative;
634
+ height: 12px;
635
+ overflow: hidden;
636
+ border-radius: 999px;
637
+ background: var(--panel-soft);
638
+ }
639
+
640
+ .progress-bar {
641
+ width: 0%;
642
+ height: 100%;
643
+ border-radius: inherit;
644
+ background: linear-gradient(90deg, var(--blue), color-mix(in srgb, var(--green) 70%, var(--blue)));
645
+ transition: width 520ms cubic-bezier(.2, .8, .2, 1), background 180ms ease;
646
+ position: relative;
647
+ }
648
+
649
+ .progress-bar.active::after {
650
+ content: "";
651
+ position: absolute;
652
+ inset: 0;
653
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .42), transparent);
654
+ animation: progress-shine 1100ms ease-in-out infinite;
655
+ }
656
+
657
+ .progress-bar.error {
658
+ background: var(--red);
659
+ }
660
+
661
+ .progress-percent {
662
+ text-align: right;
663
+ }
664
+
665
+ .review-grid {
666
+ grid-template-columns: repeat(3, minmax(0, 1fr));
667
+ }
668
+
669
+ .review-item {
670
+ border: 1px solid var(--line);
671
+ border-radius: 8px;
672
+ background: var(--panel);
673
+ padding: 15px;
674
+ box-shadow: var(--shadow);
675
+ }
676
+
677
+ .review-item span {
678
+ color: var(--muted);
679
+ display: block;
680
+ margin-bottom: 8px;
681
+ }
682
+
683
+ .review-item strong {
684
+ display: block;
685
+ overflow: hidden;
686
+ text-overflow: ellipsis;
687
+ white-space: nowrap;
688
+ }
689
+
690
+ .step-card {
691
+ min-height: 126px;
692
+ padding: 18px;
693
+ position: relative;
694
+ overflow: hidden;
695
+ }
696
+
697
+ .step-card::after {
698
+ content: "";
699
+ position: absolute;
700
+ inset: auto 0 0 0;
701
+ height: 4px;
702
+ background: var(--line);
703
+ }
704
+
705
+ .step-card.active::after {
706
+ background: var(--amber);
707
+ animation: line-pulse 1200ms ease-in-out infinite;
708
+ }
709
+
710
+ .step-card.done::after {
711
+ background: var(--green);
712
+ }
713
+
714
+ .step-card.error::after {
715
+ background: var(--red);
716
+ }
717
+
718
+ .step-card span {
719
+ display: inline-flex;
720
+ align-items: center;
721
+ justify-content: center;
722
+ width: 34px;
723
+ height: 34px;
724
+ border-radius: 8px;
725
+ background: var(--panel-soft);
726
+ color: var(--blue);
727
+ font-weight: 900;
728
+ margin-bottom: 18px;
729
+ }
730
+
731
+ .step-card strong,
732
+ .step-card small {
733
+ display: block;
734
+ }
735
+
736
+ .result-panel {
737
+ min-height: 110px;
738
+ padding: 18px;
739
+ margin-top: 18px;
740
+ display: flex;
741
+ align-items: center;
742
+ justify-content: space-between;
743
+ gap: 16px;
744
+ }
745
+
746
+ .result-panel p {
747
+ margin: 8px 0 0;
748
+ color: var(--muted);
749
+ word-break: break-all;
750
+ }
751
+
752
+ .result-actions {
753
+ display: flex;
754
+ gap: 10px;
755
+ flex: 0 0 auto;
756
+ }
757
+
758
+ .log-console {
759
+ height: min(620px, calc(100vh - 230px));
760
+ overflow: auto;
761
+ border: 1px solid var(--line);
762
+ border-radius: 8px;
763
+ background: #0c1117;
764
+ color: #d6e4f7;
765
+ padding: 18px;
766
+ font-family: "Cascadia Mono", Consolas, monospace;
767
+ font-size: 13px;
768
+ line-height: 1.55;
769
+ }
770
+
771
+ .log-line {
772
+ padding: 4px 0;
773
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
774
+ animation: log-in 220ms ease both;
775
+ white-space: pre-wrap;
776
+ }
777
+
778
+ .log-line.system {
779
+ color: #8ab4ff;
780
+ }
781
+
782
+ .log-line.success {
783
+ color: #81e0ad;
784
+ }
785
+
786
+ .log-line.error {
787
+ color: #ff8f99;
788
+ }
789
+
790
+ .log-line.animated {
791
+ color: #f4c76b;
792
+ }
793
+
794
+ .help-grid {
795
+ grid-template-columns: repeat(3, minmax(0, 1fr));
796
+ }
797
+
798
+ .help-grid article {
799
+ min-height: 160px;
800
+ padding: 20px;
801
+ }
802
+
803
+ .success-view {
804
+ min-height: 100%;
805
+ display: none;
806
+ place-items: center;
807
+ }
808
+
809
+ .success-view.active {
810
+ display: grid;
811
+ }
812
+
813
+ .success-panel {
814
+ width: min(760px, 100%);
815
+ border: 1px solid var(--line);
816
+ border-radius: 8px;
817
+ background: var(--panel);
818
+ box-shadow: var(--shadow);
819
+ padding: 34px;
820
+ text-align: center;
821
+ animation: boot-in 520ms cubic-bezier(.2, .8, .2, 1) both;
822
+ }
823
+
824
+ .success-icon {
825
+ width: 76px;
826
+ height: 76px;
827
+ object-fit: cover;
828
+ border-radius: 18px;
829
+ box-shadow: 0 18px 40px rgba(18, 111, 255, 0.24);
830
+ margin-bottom: 18px;
831
+ }
832
+
833
+ .success-panel p {
834
+ color: var(--muted);
835
+ margin-bottom: 18px;
836
+ }
837
+
838
+ .success-panel code {
839
+ display: block;
840
+ border: 1px solid var(--line);
841
+ border-radius: 8px;
842
+ background: var(--bg);
843
+ color: var(--text);
844
+ padding: 14px;
845
+ word-break: break-all;
846
+ margin: 18px 0 22px;
847
+ }
848
+
849
+ .success-panel .result-actions {
850
+ justify-content: center;
851
+ }
852
+
853
+ .bottom-log-bar {
854
+ position: fixed;
855
+ left: 0;
856
+ right: 0;
857
+ bottom: 34px;
858
+ height: var(--log-bar-height);
859
+ z-index: 14;
860
+ border-top: 1px solid var(--line);
861
+ background: color-mix(in srgb, var(--panel) 96%, var(--bg));
862
+ box-shadow: 0 -18px 42px rgba(49, 86, 130, 0.12);
863
+ padding: 10px 18px 14px;
864
+ display: grid;
865
+ grid-template-rows: 34px minmax(0, 1fr);
866
+ gap: 8px;
867
+ opacity: 0;
868
+ pointer-events: none;
869
+ transform: translateY(calc(var(--log-bar-height) + 12px));
870
+ transition: transform 220ms ease, opacity 180ms ease;
871
+ }
872
+
873
+ body.logs-visible .bottom-log-bar {
874
+ opacity: 1;
875
+ pointer-events: auto;
876
+ transform: translateY(0);
877
+ }
878
+
879
+ .bottom-log-header {
880
+ display: flex;
881
+ align-items: center;
882
+ justify-content: space-between;
883
+ gap: 12px;
884
+ }
885
+
886
+ .bottom-log-header strong {
887
+ color: var(--muted);
888
+ font-size: 13px;
889
+ text-transform: uppercase;
890
+ letter-spacing: .08em;
891
+ }
892
+
893
+ .bottom-log-actions {
894
+ display: inline-flex;
895
+ align-items: center;
896
+ gap: 8px;
897
+ }
898
+
899
+ .compact-action {
900
+ min-height: 30px;
901
+ padding: 0 12px;
902
+ font-size: 12px;
903
+ }
904
+
905
+ .bottom-log-console {
906
+ height: auto;
907
+ min-height: 0;
908
+ padding: 10px 12px;
909
+ font-size: 12px;
910
+ line-height: 1.4;
911
+ }
912
+
913
+ .statusbar {
914
+ position: fixed;
915
+ left: 0;
916
+ right: 0;
917
+ bottom: 0;
918
+ height: 34px;
919
+ border-top: 1px solid var(--line);
920
+ background: color-mix(in srgb, var(--panel) 92%, transparent);
921
+ display: flex;
922
+ align-items: center;
923
+ gap: 10px;
924
+ padding: 0 28px;
925
+ color: var(--muted);
926
+ font-size: 13px;
927
+ }
928
+
929
+ .status-log-toggle {
930
+ margin-left: auto;
931
+ min-height: 26px;
932
+ border: 1px solid var(--line);
933
+ border-radius: 8px;
934
+ background: var(--blue-soft);
935
+ color: var(--blue);
936
+ padding: 0 12px;
937
+ font-size: 12px;
938
+ font-weight: 800;
939
+ }
940
+
941
+ .status-dot {
942
+ width: 10px;
943
+ height: 10px;
944
+ border-radius: 999px;
945
+ background: var(--green);
946
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--green) 18%, transparent);
947
+ }
948
+
949
+ .status-dot.busy {
950
+ background: var(--amber);
951
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--amber) 18%, transparent);
952
+ animation: pulse 1200ms ease-in-out infinite;
953
+ }
954
+
955
+ .status-dot.error {
956
+ background: var(--red);
957
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--red) 18%, transparent);
958
+ }
959
+
960
+ .status-credit {
961
+ margin-left: 0;
962
+ }
963
+
964
+ .boot-overlay,
965
+ .modal-overlay {
966
+ position: fixed;
967
+ inset: 0;
968
+ z-index: 20;
969
+ background: var(--bg);
970
+ display: grid;
971
+ place-items: center;
972
+ }
973
+
974
+ .boot-overlay.hiding,
975
+ .modal-overlay.hiding {
976
+ animation: overlay-out 360ms ease both;
977
+ }
978
+
979
+ .boot-card,
980
+ .language-card {
981
+ width: min(440px, calc(100vw - 44px));
982
+ border: 1px solid var(--line);
983
+ border-radius: 10px;
984
+ background: var(--panel);
985
+ box-shadow: var(--shadow);
986
+ padding: 34px;
987
+ text-align: center;
988
+ animation: boot-in 600ms cubic-bezier(.2, .8, .2, 1) both;
989
+ }
990
+
991
+ .boot-icon,
992
+ .language-icon {
993
+ margin-bottom: 18px;
994
+ }
995
+
996
+ .boot-kicker {
997
+ color: var(--blue);
998
+ font-weight: 900;
999
+ }
1000
+
1001
+ .boot-card h1,
1002
+ .language-card h2 {
1003
+ margin: 12px 0 10px;
1004
+ }
1005
+
1006
+ .boot-card p,
1007
+ .language-card p {
1008
+ color: var(--muted);
1009
+ }
1010
+
1011
+ .boot-loader {
1012
+ height: 6px;
1013
+ background: var(--panel-soft);
1014
+ border-radius: 999px;
1015
+ overflow: hidden;
1016
+ margin-top: 24px;
1017
+ }
1018
+
1019
+ .boot-loader span {
1020
+ display: block;
1021
+ height: 100%;
1022
+ width: 42%;
1023
+ background: var(--blue);
1024
+ border-radius: inherit;
1025
+ animation: loader 1300ms ease-in-out infinite;
1026
+ }
1027
+
1028
+ .language-actions {
1029
+ display: flex;
1030
+ gap: 12px;
1031
+ justify-content: center;
1032
+ margin-top: 22px;
1033
+ }
1034
+
1035
+ .hidden {
1036
+ display: none !important;
1037
+ }
1038
+
1039
+ @keyframes shell-in {
1040
+ from {
1041
+ opacity: 0;
1042
+ transform: translateY(18px) scale(.985);
1043
+ }
1044
+ to {
1045
+ opacity: 1;
1046
+ transform: none;
1047
+ }
1048
+ }
1049
+
1050
+ @keyframes view-in {
1051
+ from {
1052
+ opacity: 0;
1053
+ transform: translateY(8px);
1054
+ }
1055
+ to {
1056
+ opacity: 1;
1057
+ transform: none;
1058
+ }
1059
+ }
1060
+
1061
+ @keyframes boot-in {
1062
+ from {
1063
+ opacity: 0;
1064
+ transform: translateY(18px) scale(.96);
1065
+ }
1066
+ to {
1067
+ opacity: 1;
1068
+ transform: none;
1069
+ }
1070
+ }
1071
+
1072
+ @keyframes overlay-out {
1073
+ to {
1074
+ opacity: 0;
1075
+ transform: scale(1.02);
1076
+ }
1077
+ }
1078
+
1079
+ @keyframes loader {
1080
+ 0% {
1081
+ transform: translateX(-100%);
1082
+ }
1083
+ 50% {
1084
+ transform: translateX(85%);
1085
+ }
1086
+ 100% {
1087
+ transform: translateX(250%);
1088
+ }
1089
+ }
1090
+
1091
+ @keyframes float {
1092
+ 0%, 100% {
1093
+ transform: translateY(0);
1094
+ }
1095
+ 50% {
1096
+ transform: translateY(-8px);
1097
+ }
1098
+ }
1099
+
1100
+ @keyframes pulse {
1101
+ 50% {
1102
+ transform: scale(.82);
1103
+ }
1104
+ }
1105
+
1106
+ @keyframes line-pulse {
1107
+ 50% {
1108
+ opacity: .45;
1109
+ }
1110
+ }
1111
+
1112
+ @keyframes log-in {
1113
+ from {
1114
+ opacity: 0;
1115
+ transform: translateX(-8px);
1116
+ }
1117
+ to {
1118
+ opacity: 1;
1119
+ transform: none;
1120
+ }
1121
+ }
1122
+
1123
+ @media (max-width: 980px) {
1124
+ .app-shell {
1125
+ grid-template-columns: 86px minmax(0, 1fr);
1126
+ }
1127
+
1128
+ .brand div,
1129
+ .nav-item span:last-child,
1130
+ .theme-row span:not(.nav-icon),
1131
+ .theme-row strong {
1132
+ display: none;
1133
+ }
1134
+
1135
+ .brand {
1136
+ padding-inline: 4px;
1137
+ justify-content: center;
1138
+ }
1139
+
1140
+ .nav-item,
1141
+ .theme-row {
1142
+ justify-content: center;
1143
+ padding: 0;
1144
+ }
1145
+
1146
+ .main {
1147
+ padding: 42px 28px 30px;
1148
+ }
1149
+
1150
+ .summary-grid,
1151
+ .settings-grid,
1152
+ .toggle-grid,
1153
+ .pipeline,
1154
+ .review-grid,
1155
+ .help-grid {
1156
+ grid-template-columns: 1fr;
1157
+ }
1158
+
1159
+ .icon-field {
1160
+ grid-column: span 1;
1161
+ }
1162
+
1163
+ .view-header,
1164
+ .result-panel,
1165
+ .progress-panel,
1166
+ .preference-row {
1167
+ align-items: stretch;
1168
+ flex-direction: column;
1169
+ }
1170
+
1171
+ .progress-panel {
1172
+ grid-template-columns: 1fr;
1173
+ }
1174
+
1175
+ .progress-percent {
1176
+ text-align: left;
1177
+ }
1178
+
1179
+ .success-panel {
1180
+ padding: 24px;
1181
+ }
1182
+
1183
+ .success-panel .result-actions {
1184
+ flex-direction: column;
1185
+ }
1186
+
1187
+ .status-credit {
1188
+ display: none;
1189
+ }
1190
+
1191
+ .bottom-log-header {
1192
+ align-items: stretch;
1193
+ flex-direction: column;
1194
+ }
1195
+
1196
+ .bottom-log-actions {
1197
+ justify-content: space-between;
1198
+ }
1199
+ }
1200
+
1201
+ @keyframes progress-shine {
1202
+ from {
1203
+ transform: translateX(-100%);
1204
+ }
1205
+ to {
1206
+ transform: translateX(100%);
1207
+ }
1208
+ }