pinokiod 7.3.10 → 7.3.11

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 (51) hide show
  1. package/kernel/bin/brew.js +12 -2
  2. package/kernel/bin/caddy.js +24 -20
  3. package/kernel/bin/huggingface.js +2 -2
  4. package/kernel/bin/setup.js +2 -3
  5. package/kernel/bin/uv.js +13 -6
  6. package/kernel/connect/index.js +5 -1
  7. package/kernel/connect/providers/huggingface/index.js +213 -75
  8. package/kernel/environment.js +16 -1
  9. package/kernel/router/localhost_home_router.js +7 -0
  10. package/kernel/shell.js +1 -5
  11. package/kernel/util.js +1 -0
  12. package/package.json +1 -1
  13. package/server/index.js +75 -33
  14. package/server/public/common.js +45 -71
  15. package/server/public/install.js +20 -2
  16. package/server/public/layout.js +1 -1
  17. package/server/public/style.css +1432 -511
  18. package/server/public/tab-link-popover.css +162 -18
  19. package/server/public/tab-link-popover.js +230 -21
  20. package/server/public/task-launcher.css +121 -84
  21. package/server/public/terminal-settings.js +121 -45
  22. package/server/public/universal-launcher.css +42 -33
  23. package/server/public/urldropdown.css +284 -0
  24. package/server/views/app.ejs +1595 -308
  25. package/server/views/autolaunch.ejs +4 -5
  26. package/server/views/checkpoints.ejs +223 -50
  27. package/server/views/connect/huggingface.ejs +406 -325
  28. package/server/views/connect.ejs +0 -1
  29. package/server/views/github.ejs +277 -324
  30. package/server/views/index.ejs +53 -1
  31. package/server/views/install.ejs +119 -19
  32. package/server/views/logs.ejs +10 -9
  33. package/server/views/net.ejs +341 -64
  34. package/server/views/network.ejs +85 -63
  35. package/server/views/partials/main_sidebar.ejs +237 -12
  36. package/server/views/plugins.ejs +141 -3
  37. package/server/views/settings.ejs +103 -7
  38. package/server/views/setup.ejs +0 -5
  39. package/server/views/skills.ejs +0 -1
  40. package/server/views/task_list.ejs +0 -1
  41. package/server/views/terminal.ejs +142 -1
  42. package/server/views/terminals.ejs +346 -6
  43. package/server/views/tools.ejs +828 -1691
  44. package/test/caddy-install.test.js +53 -0
  45. package/test/connect-setup.test.js +16 -0
  46. package/test/github-connection.test.js +1 -1
  47. package/test/huggingface-bin.test.js +4 -4
  48. package/test/huggingface-connect.test.js +73 -0
  49. package/test/main-sidebar.test.js +31 -0
  50. package/test/shell-run-template.test.js +5 -1
  51. package/test/uv-bin.test.js +29 -0
@@ -579,6 +579,142 @@ main.browserview {
579
579
  min-height: 0;
580
580
  display: flex;
581
581
  flex-direction: column;
582
+ position: relative;
583
+ }
584
+ .browserview-network-status {
585
+ --install-spinner-fg: rgba(31, 41, 55, 0.78);
586
+ position: absolute;
587
+ inset: 0;
588
+ z-index: 4;
589
+ display: grid;
590
+ place-items: center;
591
+ box-sizing: border-box;
592
+ padding: 24px;
593
+ text-align: center;
594
+ color: rgba(17, 24, 39, 0.9);
595
+ background: var(--app-page-canvas-bg, #fff);
596
+ pointer-events: auto;
597
+ }
598
+ .browserview-network-status[hidden] {
599
+ display: none !important;
600
+ }
601
+ body.dark .browserview-network-status {
602
+ --install-spinner-fg: rgba(248, 250, 252, 0.88);
603
+ color: rgba(248, 250, 252, 0.9);
604
+ background: var(--app-page-canvas-bg, #1b1c1d);
605
+ }
606
+ .browserview-network-status-inner {
607
+ display: flex;
608
+ flex-direction: column;
609
+ align-items: center;
610
+ gap: 8px;
611
+ max-width: min(420px, 100%);
612
+ }
613
+ .browserview-network-status-title {
614
+ font-size: 14px;
615
+ line-height: 1.3;
616
+ font-weight: 700;
617
+ }
618
+ .browserview-network-status-detail {
619
+ font-size: 12px;
620
+ line-height: 1.45;
621
+ color: rgba(75, 85, 99, 0.95);
622
+ }
623
+ body.dark .browserview-network-status-detail {
624
+ color: rgba(209, 213, 219, 0.84);
625
+ }
626
+ .browserview-network-status-route {
627
+ max-width: 100%;
628
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
629
+ font-size: 11px;
630
+ line-height: 1.4;
631
+ color: rgba(107, 114, 128, 0.88);
632
+ overflow-wrap: anywhere;
633
+ }
634
+ body.dark .browserview-network-status-route {
635
+ color: rgba(156, 163, 175, 0.86);
636
+ }
637
+ .browserview-network-status-actions {
638
+ display: flex;
639
+ flex-wrap: wrap;
640
+ gap: 8px;
641
+ justify-content: center;
642
+ margin-top: 6px;
643
+ }
644
+ .browserview-network-status .btn2 {
645
+ gap: 7px;
646
+ min-height: 30px;
647
+ padding: 6px 11px;
648
+ font-size: 12px;
649
+ font-weight: 700;
650
+ }
651
+ .browserview-network-status .browserview-network-status-primary {
652
+ border-color: rgba(0, 0, 0, 0.12);
653
+ background: rgba(255, 255, 255, 0.88);
654
+ color: rgba(17, 24, 39, 0.96);
655
+ }
656
+ .browserview-network-status .browserview-network-status-primary:hover,
657
+ .browserview-network-status .browserview-network-status-primary:focus-visible {
658
+ background: rgba(255, 255, 255, 1);
659
+ }
660
+ .browserview-network-status .browserview-network-status-secondary {
661
+ border-color: transparent;
662
+ background: transparent;
663
+ color: rgba(75, 85, 99, 0.86);
664
+ font-weight: 600;
665
+ }
666
+ .browserview-network-status .browserview-network-status-secondary:hover,
667
+ .browserview-network-status .browserview-network-status-secondary:focus-visible {
668
+ background: rgba(0, 0, 0, 0.05);
669
+ }
670
+ body.dark .browserview-network-status .browserview-network-status-primary {
671
+ border-color: rgba(255, 255, 255, 0.14);
672
+ background: rgba(255, 255, 255, 0.1);
673
+ color: rgba(248, 250, 252, 0.94);
674
+ }
675
+ body.dark .browserview-network-status .browserview-network-status-primary:hover,
676
+ body.dark .browserview-network-status .browserview-network-status-primary:focus-visible {
677
+ background: rgba(255, 255, 255, 0.15);
678
+ }
679
+ body.dark .browserview-network-status .browserview-network-status-secondary {
680
+ color: rgba(209, 213, 219, 0.78);
681
+ }
682
+ body.dark .browserview-network-status .browserview-network-status-secondary:hover,
683
+ body.dark .browserview-network-status .browserview-network-status-secondary:focus-visible {
684
+ background: rgba(255, 255, 255, 0.08);
685
+ }
686
+ .browserview-network-status .install-status-spinner {
687
+ position: relative;
688
+ display: inline-flex;
689
+ width: 18px;
690
+ height: 18px;
691
+ margin-bottom: 3px;
692
+ }
693
+ .browserview-network-status .install-status-grid-anchor,
694
+ .browserview-network-status .install-status-grid-chaser {
695
+ position: absolute;
696
+ display: block;
697
+ width: 7px;
698
+ height: 7px;
699
+ border-radius: 2px;
700
+ background: var(--install-spinner-fg);
701
+ }
702
+ .browserview-network-status .install-status-grid-anchor {
703
+ opacity: 0.16;
704
+ }
705
+ .browserview-network-status .install-status-grid-anchor-1,
706
+ .browserview-network-status .install-status-grid-chaser { top: 1px; left: 1px; }
707
+ .browserview-network-status .install-status-grid-anchor-2 { top: 1px; left: 12px; }
708
+ .browserview-network-status .install-status-grid-anchor-3 { top: 12px; left: 12px; }
709
+ .browserview-network-status .install-status-grid-anchor-4 { top: 12px; left: 1px; }
710
+ .browserview-network-status .install-status-grid-chaser {
711
+ animation: pinokio-browserview-corner-chase 1.05s cubic-bezier(0.6, 0, 0.2, 1) infinite;
712
+ }
713
+ @keyframes pinokio-browserview-corner-chase {
714
+ 0%, 100% { transform: translate(0, 0); }
715
+ 25% { transform: translate(11px, 0); }
716
+ 50% { transform: translate(11px, 11px); }
717
+ 75% { transform: translate(0, 11px); }
582
718
  }
583
719
  .community-drawer {
584
720
  display: none;
@@ -1853,9 +1989,15 @@ body.dark .appcanvas_filler {
1853
1989
  }
1854
1990
  .appcanvas.vertical .appcanvas-resizer {
1855
1991
  display: flex;
1856
- flex: 0 0 0px;
1992
+ flex: 0 0 8px;
1993
+ width: 8px;
1994
+ min-width: 8px;
1995
+ margin-left: -4px;
1996
+ margin-right: -4px;
1857
1997
  align-items: stretch;
1858
1998
  justify-content: center;
1999
+ position: relative;
2000
+ z-index: 3;
1859
2001
  cursor: col-resize;
1860
2002
  touch-action: none;
1861
2003
  outline: none;
@@ -5105,7 +5247,7 @@ body.dark .pinokio-git-diff-viewer-header {
5105
5247
  .pinokio-modal-tabs {
5106
5248
  display: inline-flex;
5107
5249
  gap: 8px;
5108
- padding: 0 6px;
5250
+ padding: 0 14px;
5109
5251
  }
5110
5252
 
5111
5253
  .pinokio-modal-tab {
@@ -6187,11 +6329,14 @@ body.dark .snapshot-footer-input input {
6187
6329
  .snapshot-footer-input input::placeholder {
6188
6330
  opacity: 0.7;
6189
6331
  }
6190
- .mobile-bottom-nav,
6191
- .mobile-sheet-actions,
6192
- .mobile-menu-fallback {
6193
- display: none;
6194
- }
6332
+ .mobile-bottom-nav,
6333
+ .mobile-sheet-actions,
6334
+ .mobile-drawer-home,
6335
+ .mobile-drawer-actions,
6336
+ .mobile-menu-backdrop,
6337
+ .mobile-menu-fallback {
6338
+ display: none;
6339
+ }
6195
6340
  header.navheader h1 {
6196
6341
  position: relative;
6197
6342
  }
@@ -6210,10 +6355,10 @@ header.navheader h1 {
6210
6355
  margin: 0 10px;
6211
6356
  }
6212
6357
  }
6213
- @media only screen and (max-width: 768px) {
6214
- :root {
6215
- --mobile-bottom-bar-height: calc(33px + env(safe-area-inset-bottom));
6216
- }
6358
+ @media only screen and (max-width: 768px) {
6359
+ :root {
6360
+ --mobile-bottom-bar-height: calc(46px + env(safe-area-inset-bottom));
6361
+ }
6217
6362
  .appcanvas.vertical {
6218
6363
  flex-direction: column;
6219
6364
  }
@@ -6239,86 +6384,92 @@ header.navheader h1 {
6239
6384
  header.navheader .app-header-identity {
6240
6385
  display: none !important;
6241
6386
  }
6242
- body:not(.mobile-menu-open) .appcanvas > aside {
6243
- display: none;
6244
- }
6245
- body.mobile-menu-open #menu-mobile-close {
6246
- display: inline-flex;
6247
- }
6248
- .browserview-shell {
6249
- box-sizing: border-box;
6250
- }
6251
- .mobile-bottom-nav {
6252
- position: sticky;
6253
- bottom: 0;
6254
- display: flex;
6255
- flex: 0 0 auto;
6256
- align-items: center;
6257
- gap: 3px;
6258
- width: 100%;
6259
- margin-top: auto;
6260
- min-height: 32px;
6261
- padding: 0 4px env(safe-area-inset-bottom) 4px;
6262
- border-top: 1px solid rgba(0,0,0,0.08);
6263
- background: rgba(255,255,255,0.96);
6264
- backdrop-filter: blur(20px);
6265
- z-index: 10000002;
6266
- box-sizing: border-box;
6267
- }
6387
+ .browserview-shell {
6388
+ box-sizing: border-box;
6389
+ }
6390
+ .mobile-bottom-nav {
6391
+ position: sticky;
6392
+ bottom: 0;
6393
+ display: flex;
6394
+ flex: 0 0 auto;
6395
+ align-items: center;
6396
+ gap: 3px;
6397
+ width: 100%;
6398
+ margin-top: auto;
6399
+ min-height: var(--mobile-bottom-bar-height);
6400
+ padding: 0 8px env(safe-area-inset-bottom);
6401
+ border-top: 1px solid rgba(0,0,0,0.08);
6402
+ background: rgba(255,255,255,0.96);
6403
+ backdrop-filter: blur(20px);
6404
+ z-index: 10000040;
6405
+ box-sizing: border-box;
6406
+ }
6268
6407
  body.dark .mobile-bottom-nav {
6269
6408
  background: rgba(15, 17, 21, 0.96);
6270
6409
  border-top-color: rgba(255,255,255,0.08);
6271
6410
  }
6272
- .mobile-bottom-nav__button {
6273
- flex: 0 0 28px;
6274
- min-width: 28px;
6275
- max-width: 28px;
6276
- min-height: 28px;
6277
- display: flex;
6278
- align-items: center;
6279
- justify-content: center;
6280
- gap: 0;
6281
- padding: 0;
6282
- border-radius: 7px;
6283
- background: transparent;
6284
- color: #64748b;
6285
- text-decoration: none;
6411
+ .mobile-bottom-nav__button {
6412
+ flex: 0 0 38px;
6413
+ width: 38px;
6414
+ min-width: 38px;
6415
+ max-width: 38px;
6416
+ height: 38px;
6417
+ min-height: 38px;
6418
+ display: flex;
6419
+ align-items: center;
6420
+ justify-content: center;
6421
+ gap: 0;
6422
+ padding: 0;
6423
+ border-radius: 8px;
6424
+ background: transparent;
6425
+ color: #64748b;
6426
+ text-decoration: none;
6286
6427
  }
6287
6428
  .mobile-bottom-nav__button i,
6288
6429
  .mobile-bottom-nav__button .ask-ai-brand-icon {
6289
6430
  font-size: 14px;
6290
6431
  }
6291
- .mobile-bottom-nav__button.selected {
6292
- background: rgba(10, 132, 255, 0.12);
6293
- color: #0a84ff;
6294
- }
6295
- body.dark .mobile-bottom-nav__button {
6296
- color: rgba(148, 163, 184, 0.9);
6297
- }
6432
+ .mobile-bottom-nav__button.selected {
6433
+ background: rgba(10, 132, 255, 0.12);
6434
+ color: #0a84ff;
6435
+ }
6436
+ .mobile-bottom-nav__button:focus {
6437
+ outline: none;
6438
+ }
6439
+ .mobile-bottom-nav__button:focus-visible {
6440
+ outline: 2px solid var(--pinokio-sidebar-separator-focus);
6441
+ outline-offset: -2px;
6442
+ }
6443
+ body.dark .mobile-bottom-nav__button {
6444
+ color: rgba(148, 163, 184, 0.9);
6445
+ }
6298
6446
  body.dark .mobile-bottom-nav__button.selected {
6299
6447
  background: rgba(10, 132, 255, 0.18);
6300
6448
  color: #63a9ff;
6301
6449
  }
6302
- .mobile-bottom-nav__logo {
6303
- width: 25px;
6304
- height: 25px;
6305
- object-fit: contain;
6306
- display: block;
6307
- }
6308
- .mobile-bottom-nav__identity {
6309
- flex: 1 1 auto;
6310
- min-width: 0;
6311
- display: flex;
6312
- align-items: center;
6313
- justify-content: center;
6314
- gap: 6px;
6315
- height: 28px;
6316
- padding: 0 10px;
6317
- border-radius: 999px;
6318
- border: 1px solid rgba(0,0,0,0.08);
6319
- background: rgba(255, 255, 255, 0.78);
6320
- box-sizing: border-box;
6321
- }
6450
+ .mobile-bottom-nav__logo {
6451
+ width: 24px;
6452
+ height: 24px;
6453
+ object-fit: contain;
6454
+ display: block;
6455
+ }
6456
+ .mobile-bottom-nav__identity {
6457
+ flex: 1 1 auto;
6458
+ min-width: 0;
6459
+ display: flex;
6460
+ align-items: center;
6461
+ justify-content: flex-start;
6462
+ align-content: center;
6463
+ flex-wrap: wrap;
6464
+ gap: 2px 5px;
6465
+ min-height: 38px;
6466
+ padding: 2px 9px;
6467
+ border-radius: 999px;
6468
+ border: 1px solid rgba(0,0,0,0.08);
6469
+ background: rgba(255, 255, 255, 0.78);
6470
+ box-sizing: border-box;
6471
+ overflow: hidden;
6472
+ }
6322
6473
  body.dark .mobile-bottom-nav__identity {
6323
6474
  border-color: rgba(255,255,255,0.08);
6324
6475
  background: rgba(255,255,255,0.06);
@@ -6330,16 +6481,17 @@ header.navheader h1 {
6330
6481
  object-fit: contain;
6331
6482
  display: block;
6332
6483
  }
6333
- .mobile-bottom-nav__identity-title {
6334
- min-width: 0;
6335
- overflow: hidden;
6336
- text-overflow: ellipsis;
6337
- white-space: nowrap;
6338
- color: #0f172a;
6339
- font-size: 12px;
6340
- font-weight: 700;
6341
- line-height: 1;
6342
- }
6484
+ .mobile-bottom-nav__identity-title {
6485
+ min-width: 0;
6486
+ max-width: 42%;
6487
+ overflow: hidden;
6488
+ text-overflow: ellipsis;
6489
+ white-space: nowrap;
6490
+ color: #0f172a;
6491
+ font-size: 11px;
6492
+ font-weight: 700;
6493
+ line-height: 1;
6494
+ }
6343
6495
  body.dark .mobile-bottom-nav__identity-title {
6344
6496
  color: rgba(248, 250, 252, 0.94);
6345
6497
  }
@@ -6353,22 +6505,19 @@ header.navheader h1 {
6353
6505
  body.dark .mobile-bottom-nav__identity-separator {
6354
6506
  background: rgba(148, 163, 184, 0.6);
6355
6507
  }
6356
- .mobile-bottom-nav__identity-disk {
6357
- flex: 0 0 auto;
6358
- display: inline-flex;
6359
- align-items: center;
6360
- min-width: 0;
6361
- max-width: 78px;
6362
- overflow: hidden;
6363
- text-overflow: ellipsis;
6364
- padding: 0;
6365
- border: 0 !important;
6366
- border-radius: 0;
6367
- color: rgba(71, 85, 105, 0.74);
6368
- font-size: 10px;
6369
- font-weight: 600;
6370
- line-height: 1;
6371
- white-space: nowrap;
6508
+ .mobile-bottom-nav__identity-disk {
6509
+ flex: 0 0 auto;
6510
+ display: inline-flex;
6511
+ align-items: center;
6512
+ min-width: 0;
6513
+ padding: 0;
6514
+ border: 0 !important;
6515
+ border-radius: 0;
6516
+ color: rgba(71, 85, 105, 0.74);
6517
+ font-size: 9.5px;
6518
+ font-weight: 600;
6519
+ line-height: 1;
6520
+ white-space: nowrap;
6372
6521
  cursor: default;
6373
6522
  }
6374
6523
  body.dark .mobile-bottom-nav__identity-disk {
@@ -6377,60 +6526,134 @@ header.navheader h1 {
6377
6526
  .mobile-bottom-nav__identity-disk i {
6378
6527
  display: none;
6379
6528
  }
6380
- .mobile-bottom-nav .resource-usage {
6381
- max-width: min(46vw, 190px);
6382
- }
6383
- .mobile-bottom-nav .resource-usage-trigger {
6384
- gap: 5px;
6385
- overflow: hidden;
6386
- }
6387
- .mobile-bottom-nav .resource-chip {
6388
- max-width: 82px;
6389
- overflow: hidden;
6390
- text-overflow: ellipsis;
6391
- font-size: 10px;
6392
- }
6393
- .mobile-bottom-nav .resource-chip--cpu,
6394
- .mobile-bottom-nav .resource-chip--ram,
6395
- .mobile-bottom-nav .resource-chip--vram {
6396
- display: none !important;
6397
- }
6398
- .mobile-bottom-nav .resource-usage-popover {
6399
- top: auto;
6400
- bottom: calc(100% + 9px);
6401
- right: -4px;
6402
- }
6403
- body.mobile-menu-open .appcanvas > aside {
6404
- display: flex;
6405
- position: fixed;
6406
- inset: 0;
6407
- bottom: var(--mobile-bottom-bar-height);
6408
- width: 100%;
6409
- max-width: none;
6410
- border-left: 0;
6411
- z-index: 10000001;
6412
- background: #f2f2f7;
6413
- }
6414
- body.mobile-menu-open .appcanvas.sidebar-collapsed > aside {
6415
- width: 100%;
6416
- min-width: 0;
6417
- max-width: none;
6418
- opacity: 1;
6419
- pointer-events: auto;
6420
- }
6529
+ .mobile-bottom-nav .resource-usage {
6530
+ flex: 1 1 120px;
6531
+ max-width: none;
6532
+ }
6533
+ .mobile-bottom-nav .resource-usage-trigger {
6534
+ width: 100%;
6535
+ height: auto;
6536
+ min-height: 0;
6537
+ justify-content: flex-start;
6538
+ align-content: center;
6539
+ flex-wrap: wrap;
6540
+ gap: 2px 5px;
6541
+ overflow: visible;
6542
+ padding: 0;
6543
+ }
6544
+ .mobile-bottom-nav .resource-usage-trigger::after {
6545
+ display: none;
6546
+ }
6547
+ .mobile-bottom-nav .resource-chip {
6548
+ flex: 0 0 auto;
6549
+ max-width: none;
6550
+ overflow: visible;
6551
+ text-overflow: clip;
6552
+ font-size: 9.5px;
6553
+ line-height: 1;
6554
+ }
6555
+ .mobile-bottom-nav .resource-chip--cpu,
6556
+ .mobile-bottom-nav .resource-chip--ram,
6557
+ .mobile-bottom-nav .resource-chip--vram {
6558
+ display: inline-flex;
6559
+ }
6560
+ .mobile-bottom-nav .resource-usage-popover {
6561
+ top: auto;
6562
+ bottom: calc(100% + 9px);
6563
+ right: -4px;
6564
+ }
6565
+ body.mobile-menu-open .mobile-menu-backdrop {
6566
+ display: block;
6567
+ position: fixed;
6568
+ inset: 0;
6569
+ bottom: var(--mobile-bottom-bar-height);
6570
+ z-index: 10000018;
6571
+ border: 0;
6572
+ padding: 0;
6573
+ background: rgba(15, 23, 42, 0.28);
6574
+ cursor: pointer;
6575
+ }
6576
+ body.mobile-menu-open .appcanvas > aside {
6577
+ display: flex;
6578
+ position: fixed;
6579
+ top: 0;
6580
+ left: 0;
6581
+ bottom: var(--mobile-bottom-bar-height);
6582
+ width: min(280px, calc(100vw - 40px));
6583
+ max-width: 100%;
6584
+ margin: 0 !important;
6585
+ padding: calc(12px + env(safe-area-inset-top)) 12px 18px;
6586
+ box-sizing: border-box;
6587
+ overflow-y: auto;
6588
+ background: var(--pinokio-sidebar-tabbar-bg);
6589
+ border-right: 1px solid var(--pinokio-sidebar-separator);
6590
+ border-left: 0;
6591
+ box-shadow: 24px 0 48px rgba(15, 23, 42, 0.12);
6592
+ transform: translateX(0);
6593
+ transition: transform 180ms ease;
6594
+ z-index: 10000020;
6595
+ }
6596
+ body.mobile-menu-open .appcanvas > aside,
6597
+ body.mobile-menu-open .mobile-menu-fallback {
6598
+ --app-mobile-drawer-tab-hover: rgba(15, 23, 42, 0.028);
6599
+ --app-mobile-drawer-tab-active-bg: rgba(15, 23, 42, 0.038);
6600
+ --app-mobile-drawer-tab-active-color: #111827;
6601
+ --app-mobile-drawer-tab-muted: rgba(31, 41, 55, 0.72);
6602
+ --app-mobile-drawer-icon-muted: rgba(31, 41, 55, 0.58);
6603
+ --app-mobile-drawer-icon-active: rgba(17, 24, 39, 0.84);
6604
+ }
6605
+ body:not(.mobile-menu-open) .appcanvas > aside {
6606
+ display: flex;
6607
+ position: fixed;
6608
+ top: 0;
6609
+ left: 0;
6610
+ bottom: var(--mobile-bottom-bar-height);
6611
+ width: min(280px, calc(100vw - 40px));
6612
+ max-width: 100%;
6613
+ margin: 0 !important;
6614
+ padding: calc(12px + env(safe-area-inset-top)) 12px 18px;
6615
+ box-sizing: border-box;
6616
+ overflow-y: auto;
6617
+ pointer-events: none;
6618
+ background: var(--pinokio-sidebar-tabbar-bg);
6619
+ border-right: 1px solid var(--pinokio-sidebar-separator);
6620
+ border-left: 0;
6621
+ box-shadow: 24px 0 48px rgba(15, 23, 42, 0.12);
6622
+ transform: translateX(-100%);
6623
+ transition: transform 180ms ease;
6624
+ z-index: 10000020;
6625
+ }
6626
+ body.mobile-menu-open .appcanvas.sidebar-collapsed > aside {
6627
+ width: min(280px, calc(100vw - 40px));
6628
+ min-width: 0;
6629
+ max-width: 100%;
6630
+ opacity: 1;
6631
+ pointer-events: auto;
6632
+ }
6421
6633
  body.mobile-menu-open .appcanvas.sidebar-collapsed > aside .menu-container {
6422
6634
  width: 100%;
6423
6635
  }
6424
- body.dark.mobile-menu-open .appcanvas > aside {
6425
- background: #0f1115;
6426
- }
6427
- body.mobile-menu-open .appcanvas > aside .menu-container {
6428
- width: 100%;
6429
- flex-direction: column;
6430
- align-items: stretch;
6431
- gap: 8px;
6432
- padding-top: 0;
6433
- }
6636
+ body.dark.mobile-menu-open .appcanvas > aside {
6637
+ background: var(--pinokio-sidebar-tabbar-bg);
6638
+ border-right-color: var(--pinokio-sidebar-separator);
6639
+ box-shadow: 24px 0 52px rgba(0, 0, 0, 0.38);
6640
+ }
6641
+ body.dark.mobile-menu-open .appcanvas > aside,
6642
+ body.dark.mobile-menu-open .mobile-menu-fallback {
6643
+ --app-mobile-drawer-tab-hover: rgba(255, 255, 255, 0.035);
6644
+ --app-mobile-drawer-tab-active-bg: rgba(255, 255, 255, 0.048);
6645
+ --app-mobile-drawer-tab-active-color: rgba(248, 250, 252, 0.91);
6646
+ --app-mobile-drawer-tab-muted: rgba(229, 231, 235, 0.64);
6647
+ --app-mobile-drawer-icon-muted: rgba(229, 231, 235, 0.54);
6648
+ --app-mobile-drawer-icon-active: rgba(248, 250, 252, 0.82);
6649
+ }
6650
+ body.mobile-menu-open .appcanvas > aside .menu-container {
6651
+ width: 100%;
6652
+ flex-direction: column;
6653
+ align-items: stretch;
6654
+ gap: 8px;
6655
+ padding-top: 0;
6656
+ }
6434
6657
  body.mobile-menu-open .appcanvas > aside .config-info {
6435
6658
  padding: 6px 8px 2px;
6436
6659
  font-size: 15px;
@@ -6445,16 +6668,16 @@ header.navheader h1 {
6445
6668
  body.dark.mobile-menu-open .appcanvas > aside .disk-usage {
6446
6669
  color: rgba(148, 163, 184, 0.9);
6447
6670
  }
6448
- body.mobile-menu-open .appcanvas > aside .menu-scroller {
6449
- flex-direction: column;
6450
- align-items: stretch;
6451
- overflow-y: auto;
6452
- overflow-x: hidden;
6453
- width: 100%;
6454
- padding: 12px 12px 14px;
6455
- gap: 12px;
6456
- box-sizing: border-box;
6457
- }
6671
+ body.mobile-menu-open .appcanvas > aside .menu-scroller {
6672
+ flex-direction: column;
6673
+ align-items: stretch;
6674
+ overflow-y: auto;
6675
+ overflow-x: hidden;
6676
+ width: 100%;
6677
+ padding: 0 0 8px;
6678
+ gap: 8px;
6679
+ box-sizing: border-box;
6680
+ }
6458
6681
  body.mobile-menu-open .appcanvas > aside .workspace-mode-switch,
6459
6682
  body.mobile-menu-open .mobile-menu-fallback .workspace-mode-switch {
6460
6683
  flex-direction: row;
@@ -6482,14 +6705,14 @@ header.navheader h1 {
6482
6705
  display: flex;
6483
6706
  flex-direction: column;
6484
6707
  align-items: stretch;
6485
- gap: 8px;
6708
+ gap: 4px;
6486
6709
  width: 100%;
6487
6710
  }
6488
- body.mobile-menu-open .appcanvas > aside .mobile-sheet-actions {
6489
- display: flex;
6490
- align-items: center;
6491
- gap: 8px;
6492
- width: 100%;
6711
+ body.mobile-menu-open .appcanvas > aside .mobile-sheet-actions {
6712
+ display: none;
6713
+ align-items: center;
6714
+ gap: 8px;
6715
+ width: 100%;
6493
6716
  overflow-x: auto;
6494
6717
  overflow-y: hidden;
6495
6718
  padding-bottom: 2px;
@@ -6546,11 +6769,11 @@ header.navheader h1 {
6546
6769
  justify-content: center;
6547
6770
  gap: 0;
6548
6771
  }
6549
- body.mobile-menu-open[data-view='files'] .mobile-menu-fallback .mobile-sheet-actions {
6550
- display: flex;
6551
- align-items: center;
6552
- gap: 8px;
6553
- width: 100%;
6772
+ body.mobile-menu-open[data-view='files'] .mobile-menu-fallback .mobile-sheet-actions {
6773
+ display: none;
6774
+ align-items: center;
6775
+ gap: 8px;
6776
+ width: 100%;
6554
6777
  overflow-x: auto;
6555
6778
  overflow-y: hidden;
6556
6779
  padding-bottom: 2px;
@@ -6560,56 +6783,195 @@ header.navheader h1 {
6560
6783
  max-width: none;
6561
6784
  min-width: 0;
6562
6785
  width: 100%;
6563
- padding: 12px 14px;
6564
- border-radius: 14px;
6565
- border: 1px solid rgba(0,0,0,0.06);
6566
- background: #fff;
6567
- color: #111827;
6568
- box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
6786
+ min-height: 36px;
6787
+ padding: 6px 9px;
6788
+ border-radius: 6px;
6789
+ border: 0;
6790
+ background: transparent;
6791
+ color: var(--app-mobile-drawer-tab-muted);
6792
+ box-shadow: none;
6569
6793
  box-sizing: border-box;
6570
- min-height: 44px;
6571
6794
  }
6572
6795
  body.dark.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2),
6573
6796
  body.dark.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2) {
6574
- background: rgba(15, 17, 21, 0.8);
6575
- border-color: rgba(255,255,255,0.08);
6576
- color: rgba(226, 232, 240, 0.9);
6577
- box-shadow: 0 1px 2px rgba(2, 6, 20, 0.4);
6797
+ background: transparent;
6798
+ border-color: transparent;
6799
+ color: var(--app-mobile-drawer-tab-muted);
6800
+ box-shadow: none;
6801
+ }
6802
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2):hover,
6803
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2):focus-visible,
6804
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2):hover,
6805
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2):focus-visible {
6806
+ background: var(--app-mobile-drawer-tab-hover);
6807
+ color: var(--app-mobile-drawer-tab-active-color);
6808
+ }
6809
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn.selected:not(.btn2),
6810
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn.selected:not(.btn2) {
6811
+ background: var(--app-mobile-drawer-tab-active-bg) !important;
6812
+ color: var(--app-mobile-drawer-tab-active-color);
6578
6813
  }
6579
6814
  body.mobile-menu-open .appcanvas > aside .menu-scroller .tab,
6580
6815
  body.mobile-menu-open .appcanvas > aside .menu-actions .tab {
6581
- gap: 12px;
6816
+ gap: 10px;
6817
+ font-size: 12px;
6818
+ line-height: 1.25;
6819
+ font-weight: 500;
6582
6820
  }
6583
6821
  body.mobile-menu-open .appcanvas > aside .menu-scroller .display,
6584
6822
  body.mobile-menu-open .appcanvas > aside .menu-actions .display {
6585
- font-size: 15px;
6823
+ font-size: 12px;
6824
+ line-height: 1.25;
6825
+ font-weight: 500;
6826
+ }
6827
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn.selected .tab,
6828
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn.selected .tab,
6829
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn.selected .display,
6830
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn.selected .display {
6831
+ font-weight: 600 !important;
6586
6832
  }
6587
6833
  body.mobile-menu-open .appcanvas > aside .menu-scroller .tab i,
6588
6834
  body.mobile-menu-open .appcanvas > aside .menu-actions .tab i {
6589
- font-size: 15px;
6835
+ color: var(--app-mobile-drawer-icon-muted) !important;
6836
+ font-size: 14px !important;
6837
+ opacity: 1;
6590
6838
  }
6591
- body.mobile-menu-open .appcanvas > aside .menu-actions {
6592
- display: none;
6839
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2):hover .tab i,
6840
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2):focus-visible .tab i,
6841
+ body.mobile-menu-open .appcanvas > aside .menu-scroller .btn.selected:not(.btn2) .tab i,
6842
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2):hover .tab i,
6843
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2):focus-visible .tab i,
6844
+ body.mobile-menu-open .appcanvas > aside .menu-actions .btn.selected:not(.btn2) .tab i {
6845
+ color: var(--app-mobile-drawer-icon-active) !important;
6593
6846
  }
6594
- .mobile-menu-fallback {
6847
+ body.mobile-menu-open .appcanvas > aside .menu-actions {
6595
6848
  display: none;
6596
6849
  }
6597
- body.mobile-menu-open[data-view='files'] .mobile-menu-fallback {
6850
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions,
6851
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions {
6598
6852
  display: flex;
6599
- position: fixed;
6600
- inset: 0;
6601
- bottom: var(--mobile-bottom-bar-height);
6602
- z-index: 10000001;
6603
6853
  flex-direction: column;
6604
- background: #f2f2f7;
6854
+ align-items: stretch;
6855
+ gap: 4px;
6856
+ width: 100%;
6857
+ margin-top: 8px;
6858
+ padding-top: 8px;
6859
+ border-top: 1px solid var(--pinokio-sidebar-separator);
6860
+ }
6861
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item,
6862
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item {
6863
+ display: flex;
6864
+ max-width: none;
6865
+ min-width: 0;
6866
+ width: 100%;
6867
+ min-height: 36px;
6868
+ padding: 6px 9px;
6869
+ border-radius: 6px;
6870
+ border: 0;
6871
+ background: transparent;
6872
+ color: var(--app-mobile-drawer-tab-muted);
6873
+ box-shadow: none;
6874
+ box-sizing: border-box;
6875
+ text-align: left;
6876
+ text-decoration: none;
6605
6877
  }
6606
- body.dark.mobile-menu-open[data-view='files'] .mobile-menu-fallback {
6607
- background: #0f1115;
6878
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item:hover,
6879
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item:focus-visible,
6880
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item:hover,
6881
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item:focus-visible {
6882
+ background: var(--app-mobile-drawer-tab-hover);
6883
+ color: var(--app-mobile-drawer-tab-active-color);
6608
6884
  }
6609
- .mobile-menu-fallback__header {
6885
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item.selected,
6886
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item.selected {
6887
+ background: var(--app-mobile-drawer-tab-active-bg);
6888
+ color: var(--app-mobile-drawer-tab-active-color);
6889
+ }
6890
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .tab,
6891
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .tab {
6610
6892
  display: flex;
6611
6893
  align-items: center;
6612
6894
  gap: 10px;
6895
+ width: 100%;
6896
+ min-width: 0;
6897
+ padding: 0;
6898
+ }
6899
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .menu-action-leading-icon,
6900
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .menu-action-leading-icon {
6901
+ width: 16px;
6902
+ height: 16px;
6903
+ flex: 0 0 16px;
6904
+ display: inline-flex;
6905
+ align-items: center;
6906
+ justify-content: center;
6907
+ line-height: 1;
6908
+ margin-right: 0;
6909
+ padding: 0;
6910
+ color: var(--app-mobile-drawer-icon-muted) !important;
6911
+ opacity: 1;
6912
+ }
6913
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions i.menu-action-leading-icon,
6914
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions i.menu-action-leading-icon {
6915
+ font-size: 14px !important;
6916
+ }
6917
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item:hover .menu-action-leading-icon,
6918
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item:focus-visible .menu-action-leading-icon,
6919
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item.selected .menu-action-leading-icon,
6920
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item:hover .menu-action-leading-icon,
6921
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item:focus-visible .menu-action-leading-icon,
6922
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item.selected .menu-action-leading-icon {
6923
+ color: var(--app-mobile-drawer-icon-active) !important;
6924
+ }
6925
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .ask-ai-brand-icon.menu-action-leading-icon,
6926
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .ask-ai-brand-icon.menu-action-leading-icon {
6927
+ -webkit-mask: url('/pinokio-mark.svg') center / 14px 14px no-repeat;
6928
+ mask: url('/pinokio-mark.svg') center / 14px 14px no-repeat;
6929
+ }
6930
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .display,
6931
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .display {
6932
+ min-width: 0;
6933
+ overflow: hidden;
6934
+ text-overflow: ellipsis;
6935
+ white-space: nowrap;
6936
+ font-size: 12px;
6937
+ line-height: 1.25;
6938
+ font-weight: 500;
6939
+ }
6940
+ body.mobile-menu-open .appcanvas > aside .mobile-drawer-actions .header-item.selected .display,
6941
+ body.mobile-menu-open .mobile-menu-fallback .mobile-drawer-actions .header-item.selected .display {
6942
+ font-weight: 600 !important;
6943
+ }
6944
+ .mobile-menu-fallback {
6945
+ display: none;
6946
+ }
6947
+ body.mobile-menu-open[data-view='files'] .mobile-menu-fallback {
6948
+ display: flex;
6949
+ position: fixed;
6950
+ top: 0;
6951
+ left: 0;
6952
+ bottom: var(--mobile-bottom-bar-height);
6953
+ width: min(280px, calc(100vw - 40px));
6954
+ max-width: 100%;
6955
+ z-index: 10000020;
6956
+ flex-direction: column;
6957
+ padding: calc(12px + env(safe-area-inset-top)) 12px 18px;
6958
+ box-sizing: border-box;
6959
+ overflow-y: auto;
6960
+ background: var(--pinokio-sidebar-tabbar-bg);
6961
+ border-right: 1px solid var(--pinokio-sidebar-separator);
6962
+ box-shadow: 24px 0 48px rgba(15, 23, 42, 0.12);
6963
+ transform: translateX(0);
6964
+ transition: transform 180ms ease;
6965
+ }
6966
+ body.dark.mobile-menu-open[data-view='files'] .mobile-menu-fallback {
6967
+ background: var(--pinokio-sidebar-tabbar-bg);
6968
+ border-right-color: var(--pinokio-sidebar-separator);
6969
+ box-shadow: 24px 0 52px rgba(0, 0, 0, 0.38);
6970
+ }
6971
+ .mobile-menu-fallback__header {
6972
+ display: flex;
6973
+ align-items: center;
6974
+ gap: 10px;
6613
6975
  padding: 12px;
6614
6976
  font-size: 15px;
6615
6977
  font-weight: 700;
@@ -6620,12 +6982,12 @@ header.navheader h1 {
6620
6982
  object-fit: contain;
6621
6983
  display: block;
6622
6984
  }
6623
- .mobile-menu-fallback__body {
6624
- flex: 1 1 auto;
6625
- overflow-y: auto;
6626
- padding: 0 12px 16px;
6627
- box-sizing: border-box;
6628
- }
6985
+ .mobile-menu-fallback__body {
6986
+ flex: 1 1 auto;
6987
+ overflow-y: auto;
6988
+ padding: 0 0 16px;
6989
+ box-sizing: border-box;
6990
+ }
6629
6991
  .mobile-menu-fallback .workspace-mode-switch {
6630
6992
  display: flex;
6631
6993
  align-items: center;
@@ -6641,12 +7003,9 @@ header.navheader h1 {
6641
7003
  border-color: rgba(255, 255, 255, 0.075);
6642
7004
  background: rgba(255, 255, 255, 0.045);
6643
7005
  }
6644
- body.mobile-menu-open .appcanvas .container {
6645
- display: none;
6646
- }
6647
- #community-toggle {
6648
- display: none;
6649
- }
7006
+ #community-toggle {
7007
+ display: none;
7008
+ }
6650
7009
  .appcanvas.panel-open .ask-ai-drawer,
6651
7010
  .appcanvas.logs-open .app-logs-drawer,
6652
7011
  .appcanvas.event-drawer-open .event-launch-drawer,
@@ -6686,11 +7045,533 @@ header.navheader h1 {
6686
7045
  .appcanvas.community-mode .community-resizer {
6687
7046
  display: none;
6688
7047
  }
6689
- .appcanvas.community-mode main.browserview {
6690
- display: none;
7048
+ .appcanvas.community-mode main.browserview {
7049
+ display: none;
7050
+ }
7051
+ .appcanvas.community-mode .browserview-shell {
7052
+ flex: 1 1 auto;
7053
+ }
7054
+ }
7055
+
7056
+ /* Minimal modal normalization: shared app SweetAlert and custom git shells. */
7057
+ :root {
7058
+ --pinokio-modal-bg: #ffffff;
7059
+ --pinokio-modal-surface-bg: #ffffff;
7060
+ --pinokio-modal-text: #18181b;
7061
+ --pinokio-modal-title-color: #18181b;
7062
+ --pinokio-modal-subtitle-color: #71717a;
7063
+ --pinokio-modal-border: rgba(24, 24, 27, 0.12);
7064
+ --pinokio-modal-border-strong: rgba(24, 24, 27, 0.2);
7065
+ --pinokio-modal-body-bg: rgba(24, 24, 27, 0.03);
7066
+ --pinokio-modal-body-border: rgba(24, 24, 27, 0.1);
7067
+ --pinokio-modal-body-iframe-bg: #ffffff;
7068
+ --pinokio-modal-body-text-color: #3f3f46;
7069
+ --pinokio-modal-label-color: #52525b;
7070
+ --pinokio-modal-input-bg: #ffffff;
7071
+ --pinokio-modal-input-border: rgba(24, 24, 27, 0.16);
7072
+ --pinokio-modal-input-text: #18181b;
7073
+ --pinokio-modal-input-focus-border: rgba(24, 24, 27, 0.42);
7074
+ --pinokio-modal-input-focus-shadow: rgba(24, 24, 27, 0.12);
7075
+ --pinokio-modal-checkbox-color: #52525b;
7076
+ --pinokio-modal-icon-bg: rgba(24, 24, 27, 0.04);
7077
+ --pinokio-modal-icon-color: #52525b;
7078
+ --pinokio-modal-primary-bg: #18181b;
7079
+ --pinokio-modal-primary-hover: #27272a;
7080
+ --pinokio-modal-primary-text: #ffffff;
7081
+ --pinokio-modal-secondary-bg: transparent;
7082
+ --pinokio-modal-secondary-hover-bg: rgba(24, 24, 27, 0.06);
7083
+ --pinokio-pill-bg: rgba(24, 24, 27, 0.05);
7084
+ --pinokio-pill-text: #3f3f46;
7085
+ --pinokio-history-empty-color: #71717a;
7086
+ --pinokio-modern-shadow: 0 18px 50px rgba(15, 23, 42, 0.16);
7087
+ --pinokio-modern-close-color: #71717a;
7088
+ --pinokio-modern-close-hover-bg: rgba(24, 24, 27, 0.06);
7089
+ --pinokio-modern-close-hover-color: #18181b;
7090
+ --pinokio-modern-cancel-bg: transparent;
7091
+ --pinokio-modern-cancel-color: #52525b;
7092
+ --pinokio-modern-cancel-hover-bg: rgba(24, 24, 27, 0.06);
7093
+ --pinokio-custom-commit-overlay-bg: rgba(9, 11, 15, 0.34);
7094
+ --pinokio-custom-commit-modal-bg: #ffffff;
7095
+ --pinokio-custom-commit-modal-text: #18181b;
7096
+ --pinokio-custom-commit-border: rgba(24, 24, 27, 0.12);
7097
+ --pinokio-custom-commit-header-bg: #ffffff;
7098
+ --pinokio-custom-commit-close-color: #71717a;
7099
+ --pinokio-custom-commit-close-hover-bg: rgba(24, 24, 27, 0.06);
7100
+ --pinokio-custom-commit-close-hover-color: #18181b;
7101
+ --pinokio-custom-commit-action-bg: transparent;
7102
+ --pinokio-custom-commit-action-border: rgba(24, 24, 27, 0.16);
7103
+ --pinokio-custom-commit-action-color: #18181b;
7104
+ --pinokio-custom-commit-action-hover: rgba(24, 24, 27, 0.06);
7105
+ }
7106
+
7107
+ body.dark {
7108
+ --pinokio-modal-bg: #1b1c1d;
7109
+ --pinokio-modal-surface-bg: #1b1c1d;
7110
+ --pinokio-modal-text: rgba(250, 250, 250, 0.94);
7111
+ --pinokio-modal-title-color: rgba(250, 250, 250, 0.94);
7112
+ --pinokio-modal-subtitle-color: rgba(229, 231, 235, 0.62);
7113
+ --pinokio-modal-border: rgba(255, 255, 255, 0.1);
7114
+ --pinokio-modal-border-strong: rgba(255, 255, 255, 0.18);
7115
+ --pinokio-modal-body-bg: rgba(255, 255, 255, 0.04);
7116
+ --pinokio-modal-body-border: rgba(255, 255, 255, 0.09);
7117
+ --pinokio-modal-body-iframe-bg: #161718;
7118
+ --pinokio-modal-body-text-color: rgba(229, 231, 235, 0.78);
7119
+ --pinokio-modal-label-color: rgba(229, 231, 235, 0.76);
7120
+ --pinokio-modal-input-bg: rgba(255, 255, 255, 0.04);
7121
+ --pinokio-modal-input-border: rgba(255, 255, 255, 0.14);
7122
+ --pinokio-modal-input-text: rgba(250, 250, 250, 0.94);
7123
+ --pinokio-modal-input-focus-border: rgba(255, 255, 255, 0.38);
7124
+ --pinokio-modal-input-focus-shadow: rgba(255, 255, 255, 0.14);
7125
+ --pinokio-modal-checkbox-color: rgba(229, 231, 235, 0.76);
7126
+ --pinokio-modal-icon-bg: rgba(255, 255, 255, 0.055);
7127
+ --pinokio-modal-icon-color: rgba(229, 231, 235, 0.76);
7128
+ --pinokio-modal-primary-bg: rgba(250, 250, 250, 0.94);
7129
+ --pinokio-modal-primary-hover: #ffffff;
7130
+ --pinokio-modal-primary-text: #1b1c1d;
7131
+ --pinokio-modal-secondary-hover-bg: rgba(255, 255, 255, 0.07);
7132
+ --pinokio-pill-bg: rgba(255, 255, 255, 0.055);
7133
+ --pinokio-pill-text: rgba(229, 231, 235, 0.76);
7134
+ --pinokio-history-empty-color: rgba(229, 231, 235, 0.58);
7135
+ --pinokio-modern-shadow: 0 24px 72px rgba(0, 0, 0, 0.42);
7136
+ --pinokio-modern-close-color: rgba(229, 231, 235, 0.58);
7137
+ --pinokio-modern-close-hover-bg: rgba(255, 255, 255, 0.07);
7138
+ --pinokio-modern-close-hover-color: rgba(250, 250, 250, 0.94);
7139
+ --pinokio-modern-cancel-bg: transparent;
7140
+ --pinokio-modern-cancel-color: rgba(229, 231, 235, 0.7);
7141
+ --pinokio-modern-cancel-hover-bg: rgba(255, 255, 255, 0.07);
7142
+ --pinokio-custom-commit-overlay-bg: rgba(0, 0, 0, 0.58);
7143
+ --pinokio-custom-commit-modal-bg: #1b1c1d;
7144
+ --pinokio-custom-commit-modal-text: rgba(250, 250, 250, 0.94);
7145
+ --pinokio-custom-commit-border: rgba(255, 255, 255, 0.1);
7146
+ --pinokio-custom-commit-header-bg: #1b1c1d;
7147
+ --pinokio-custom-commit-close-color: rgba(229, 231, 235, 0.58);
7148
+ --pinokio-custom-commit-close-hover-bg: rgba(255, 255, 255, 0.07);
7149
+ --pinokio-custom-commit-close-hover-color: rgba(250, 250, 250, 0.94);
7150
+ --pinokio-custom-commit-action-bg: transparent;
7151
+ --pinokio-custom-commit-action-border: rgba(255, 255, 255, 0.14);
7152
+ --pinokio-custom-commit-action-color: rgba(250, 250, 250, 0.94);
7153
+ --pinokio-custom-commit-action-hover: rgba(255, 255, 255, 0.07);
7154
+ }
7155
+
7156
+ .pinokio-modern-modal.swal2-popup,
7157
+ .pinokio-no-changes-popup.swal2-popup {
7158
+ background: var(--pinokio-modal-bg) !important;
7159
+ color: var(--pinokio-modal-text) !important;
7160
+ border: 1px solid var(--pinokio-modal-border) !important;
7161
+ border-radius: 8px !important;
7162
+ box-shadow: var(--pinokio-modern-shadow) !important;
7163
+ }
7164
+
7165
+ .pinokio-no-changes-popup.swal2-popup {
7166
+ max-width: 360px !important;
7167
+ padding: 22px !important;
7168
+ }
7169
+
7170
+ .pinokio-no-changes-popup .pinokio-no-changes-icon,
7171
+ .pinokio-github-login__icon,
7172
+ .pinokio-modal-icon {
7173
+ width: 32px !important;
7174
+ height: 32px !important;
7175
+ border-radius: 7px !important;
7176
+ background: var(--pinokio-modal-icon-bg) !important;
7177
+ color: var(--pinokio-modal-icon-color) !important;
7178
+ font-size: 14px !important;
7179
+ }
7180
+
7181
+ .pinokio-modal-icon--warning {
7182
+ background: rgba(217, 119, 6, 0.1) !important;
7183
+ color: #b45309 !important;
7184
+ }
7185
+
7186
+ body.dark .pinokio-modal-icon--warning {
7187
+ background: rgba(251, 191, 36, 0.12) !important;
7188
+ color: #fbbf24 !important;
7189
+ }
7190
+
7191
+ .pinokio-modern-close {
7192
+ top: 12px !important;
7193
+ right: 12px !important;
7194
+ width: 28px !important;
7195
+ height: 28px !important;
7196
+ border-radius: 6px !important;
7197
+ color: var(--pinokio-modern-close-color) !important;
7198
+ font-size: 18px !important;
7199
+ }
7200
+
7201
+ .pinokio-modern-close:hover,
7202
+ .pinokio-modern-close:focus-visible {
7203
+ background: var(--pinokio-modern-close-hover-bg) !important;
7204
+ color: var(--pinokio-modern-close-hover-color) !important;
7205
+ outline: none !important;
7206
+ }
7207
+
7208
+ .pinokio-modern-confirm.swal2-confirm,
7209
+ .pinokio-no-changes-confirm.swal2-confirm,
7210
+ .pinokio-publish-close-btn,
7211
+ .pinokio-save-version-btn,
7212
+ .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn,
7213
+ .swal2-popup.pinokio-history-modal .pinokio-save-version-btn,
7214
+ body.dark .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn,
7215
+ body.dark .swal2-popup.pinokio-history-modal .pinokio-save-version-btn {
7216
+ min-height: 32px !important;
7217
+ padding: 0 12px !important;
7218
+ border-radius: 6px !important;
7219
+ border: 1px solid var(--pinokio-modal-primary-bg) !important;
7220
+ background: var(--pinokio-modal-primary-bg) !important;
7221
+ background-color: var(--pinokio-modal-primary-bg) !important;
7222
+ color: var(--pinokio-modal-primary-text) !important;
7223
+ box-shadow: none !important;
7224
+ font-size: 13px !important;
7225
+ font-weight: 600 !important;
7226
+ }
7227
+
7228
+ .pinokio-modern-confirm.swal2-confirm:hover,
7229
+ .pinokio-no-changes-confirm.swal2-confirm:hover,
7230
+ .pinokio-publish-close-btn:hover,
7231
+ .pinokio-save-version-btn:hover,
7232
+ .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn:hover,
7233
+ .swal2-popup.pinokio-history-modal .pinokio-save-version-btn:hover,
7234
+ body.dark .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn:hover,
7235
+ body.dark .swal2-popup.pinokio-history-modal .pinokio-save-version-btn:hover {
7236
+ border-color: var(--pinokio-modal-primary-hover) !important;
7237
+ background: var(--pinokio-modal-primary-hover) !important;
7238
+ background-color: var(--pinokio-modal-primary-hover) !important;
7239
+ color: var(--pinokio-modal-primary-text) !important;
7240
+ }
7241
+
7242
+ .pinokio-save-version-btn:disabled,
7243
+ .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn:disabled,
7244
+ .swal2-popup.pinokio-history-modal .pinokio-save-version-btn:disabled,
7245
+ body.dark .swal2-popup.pinokio-diff-modal .pinokio-save-version-btn:disabled,
7246
+ body.dark .swal2-popup.pinokio-history-modal .pinokio-save-version-btn:disabled {
7247
+ border-color: var(--pinokio-modal-border) !important;
7248
+ background: var(--pinokio-modal-body-bg) !important;
7249
+ background-color: var(--pinokio-modal-body-bg) !important;
7250
+ color: var(--pinokio-modal-subtitle-color) !important;
7251
+ }
7252
+
7253
+ .pinokio-modern-cancel.swal2-cancel,
7254
+ .pinokio-modal-secondary-btn {
7255
+ min-height: 32px !important;
7256
+ margin-right: 8px !important;
7257
+ padding: 0 12px !important;
7258
+ border-radius: 6px !important;
7259
+ border: 1px solid var(--pinokio-modal-border) !important;
7260
+ background: var(--pinokio-modal-secondary-bg) !important;
7261
+ color: var(--pinokio-modern-cancel-color) !important;
7262
+ box-shadow: none !important;
7263
+ font-size: 13px !important;
7264
+ font-weight: 600 !important;
7265
+ }
7266
+
7267
+ .pinokio-modern-cancel.swal2-cancel:hover,
7268
+ .pinokio-modern-cancel.swal2-cancel:focus-visible,
7269
+ .pinokio-modal-secondary-btn:hover,
7270
+ .pinokio-modal-secondary-btn:focus-visible {
7271
+ border-color: var(--pinokio-modal-border-strong) !important;
7272
+ background: var(--pinokio-modern-cancel-hover-bg) !important;
7273
+ color: var(--pinokio-modal-title-color) !important;
7274
+ outline: none !important;
7275
+ }
7276
+
7277
+ .pinokio-modal-surface {
7278
+ padding: 0 !important;
7279
+ gap: 0 !important;
7280
+ color: var(--pinokio-modal-text) !important;
7281
+ }
7282
+
7283
+ .pinokio-modal-header {
7284
+ gap: 10px !important;
7285
+ padding: 14px !important;
7286
+ align-items: flex-start !important;
7287
+ }
7288
+
7289
+ .pinokio-modal-heading {
7290
+ gap: 3px !important;
7291
+ }
7292
+
7293
+ .pinokio-modal-title,
7294
+ .pinokio-github-login__title,
7295
+ .pinokio-no-changes-popup .pinokio-no-changes-title {
7296
+ color: var(--pinokio-modal-title-color) !important;
7297
+ font-size: 16px !important;
7298
+ line-height: 1.25 !important;
7299
+ font-weight: 600 !important;
7300
+ }
7301
+
7302
+ .pinokio-modal-subtitle,
7303
+ .pinokio-github-login__body,
7304
+ .pinokio-no-changes-popup .pinokio-no-changes-body,
7305
+ .pinokio-no-changes-popup .pinokio-no-changes-hint {
7306
+ color: var(--pinokio-modal-subtitle-color) !important;
7307
+ font-size: 12px !important;
7308
+ line-height: 1.45 !important;
7309
+ }
7310
+
7311
+ .pinokio-github-login {
7312
+ padding: 24px 22px 20px !important;
7313
+ gap: 10px !important;
7314
+ }
7315
+
7316
+ .pinokio-modal-body {
7317
+ border-top: 1px solid var(--pinokio-modal-body-border) !important;
7318
+ background: var(--pinokio-modal-body-bg) !important;
7319
+ color: var(--pinokio-modal-body-text-color) !important;
7320
+ padding: 12px 14px !important;
7321
+ }
7322
+
7323
+ .pinokio-modal-body--iframe,
7324
+ .pinokio-modal-body--diff {
7325
+ padding: 0 !important;
7326
+ }
7327
+
7328
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-tabs {
7329
+ margin-bottom: 16px !important;
7330
+ }
7331
+
7332
+ .pinokio-modal-body--iframe iframe {
7333
+ background: var(--pinokio-modal-body-iframe-bg) !important;
7334
+ }
7335
+
7336
+ .pinokio-modal-footer {
7337
+ gap: 8px !important;
7338
+ padding: 12px 14px 14px !important;
7339
+ border-top: 1px solid var(--pinokio-modal-body-border);
7340
+ background: var(--pinokio-modal-bg);
7341
+ }
7342
+
7343
+ .pinokio-modal-footer--commit {
7344
+ padding-top: 10px !important;
7345
+ }
7346
+
7347
+ .pinokio-modal-tab,
7348
+ .pinokio-history-inline-btn,
7349
+ .pinokio-history-latest-btn,
7350
+ .pinokio-git-commit-switch-btn,
7351
+ .pinokio-git-diff-open-file {
7352
+ border: 1px solid var(--pinokio-modal-border) !important;
7353
+ border-radius: 6px !important;
7354
+ background: transparent !important;
7355
+ color: var(--pinokio-modal-body-text-color) !important;
7356
+ box-shadow: none !important;
7357
+ }
7358
+
7359
+ .pinokio-modal-tab:hover,
7360
+ .pinokio-modal-tab--active,
7361
+ .pinokio-history-inline-btn:hover,
7362
+ .pinokio-history-latest-btn:hover,
7363
+ .pinokio-git-commit-switch-btn:hover,
7364
+ .pinokio-git-diff-open-file:hover {
7365
+ border-color: var(--pinokio-modal-border-strong) !important;
7366
+ background: var(--pinokio-modal-secondary-hover-bg) !important;
7367
+ color: var(--pinokio-modal-title-color) !important;
7368
+ transform: none !important;
7369
+ }
7370
+
7371
+ .pinokio-history-latest-banner,
7372
+ .pinokio-fork-item,
7373
+ .pinokio-git-commit-item,
7374
+ body.dark .pinokio-git-commit-item {
7375
+ border: 1px solid var(--pinokio-modal-border) !important;
7376
+ border-radius: 7px !important;
7377
+ background: var(--pinokio-modal-body-bg) !important;
7378
+ color: var(--pinokio-modal-body-text-color) !important;
7379
+ box-shadow: none !important;
7380
+ }
7381
+
7382
+ .pinokio-fork-help,
7383
+ .pinokio-fork-item-url,
7384
+ .pinokio-fork-name-input label,
7385
+ .pinokio-fork-org-input label,
7386
+ .pinokio-fork-org-hint,
7387
+ .pinokio-fork-dropdown-remote,
7388
+ .pinokio-publish-dropdown-remote,
7389
+ body.dark .pinokio-fork-dropdown-remote,
7390
+ body.dark .pinokio-publish-dropdown-remote {
7391
+ color: var(--pinokio-modal-subtitle-color) !important;
7392
+ }
7393
+
7394
+ .pinokio-pill {
7395
+ border: 1px solid var(--pinokio-modal-border);
7396
+ border-radius: 6px !important;
7397
+ background: var(--pinokio-pill-bg) !important;
7398
+ color: var(--pinokio-pill-text) !important;
7399
+ padding: 3px 7px !important;
7400
+ }
7401
+
7402
+ .pinokio-modal-input {
7403
+ border-radius: 6px !important;
7404
+ border: 1px solid var(--pinokio-modal-input-border) !important;
7405
+ background: var(--pinokio-modal-input-bg) !important;
7406
+ color: var(--pinokio-modal-input-text) !important;
7407
+ box-shadow: none !important;
7408
+ font-size: 13px !important;
7409
+ }
7410
+
7411
+ .pinokio-modal-input:focus {
7412
+ border-color: var(--pinokio-modal-input-focus-border) !important;
7413
+ box-shadow: 0 0 0 3px var(--pinokio-modal-input-focus-shadow) !important;
7414
+ }
7415
+
7416
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio-commit-message-container {
7417
+ align-items: stretch !important;
7418
+ }
7419
+
7420
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio-commit-actions {
7421
+ display: flex !important;
7422
+ align-items: stretch !important;
7423
+ }
7424
+
7425
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio-commit-message-input,
7426
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio-save-version-btn {
7427
+ box-sizing: border-box !important;
7428
+ height: 44px !important;
7429
+ min-height: 44px !important;
7430
+ }
7431
+
7432
+ .swal2-popup.pinokio-diff-modal .pinokio-modal-footer--commit .pinokio-save-version-btn {
7433
+ align-self: stretch !important;
7434
+ padding: 0 16px !important;
7435
+ }
7436
+
7437
+ .swal2-popup.pinokio-history-modal .pinokio-history-meta {
7438
+ padding: 0 14px 10px !important;
7439
+ gap: 6px !important;
7440
+ }
7441
+
7442
+ .swal2-popup.pinokio-history-modal .pinokio-pill {
7443
+ border-radius: 4px !important;
7444
+ font-size: 12px !important;
7445
+ line-height: 1.2 !important;
7446
+ padding: 5px 8px !important;
7447
+ }
7448
+
7449
+ .swal2-popup.pinokio-history-modal .pinokio-history-latest-banner {
7450
+ margin: 0 14px 10px !important;
7451
+ padding: 8px 10px !important;
7452
+ gap: 8px !important;
7453
+ border-radius: 4px !important;
7454
+ }
7455
+
7456
+ .swal2-popup.pinokio-history-modal .pinokio-history-latest-text {
7457
+ font-size: 13px !important;
7458
+ }
7459
+
7460
+ .swal2-popup.pinokio-history-modal .pinokio-history-actions {
7461
+ gap: 8px !important;
7462
+ }
7463
+
7464
+ .swal2-popup.pinokio-history-modal .pinokio-history-latest-btn,
7465
+ .swal2-popup.pinokio-history-modal .pinokio-history-branch-select.pinokio-modal-input {
7466
+ box-sizing: border-box !important;
7467
+ height: 32px !important;
7468
+ min-height: 32px !important;
7469
+ padding: 0 10px !important;
7470
+ font-size: 12px !important;
7471
+ }
7472
+
7473
+ .swal2-popup.pinokio-history-modal .pinokio-modal-body--history {
7474
+ padding: 0 !important;
7475
+ background: var(--pinokio-modal-bg) !important;
7476
+ }
7477
+
7478
+ .swal2-popup.pinokio-history-modal .pinokio-git-history-list {
7479
+ gap: 0 !important;
7480
+ padding: 0 14px 14px !important;
7481
+ }
7482
+
7483
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-item,
7484
+ body.dark .swal2-popup.pinokio-history-modal .pinokio-git-commit-item {
7485
+ align-items: center !important;
7486
+ gap: 10px !important;
7487
+ min-height: 52px !important;
7488
+ padding: 8px 10px !important;
7489
+ border: 0 !important;
7490
+ border-bottom: 1px solid var(--pinokio-modal-border) !important;
7491
+ border-radius: 0 !important;
7492
+ background: transparent !important;
7493
+ color: var(--pinokio-modal-body-text-color) !important;
7494
+ }
7495
+
7496
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-item:hover {
7497
+ background: var(--pinokio-modal-secondary-hover-bg) !important;
7498
+ transform: none !important;
7499
+ }
7500
+
7501
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-avatar {
7502
+ width: 28px !important;
7503
+ height: 28px !important;
7504
+ border-radius: 4px !important;
7505
+ font-size: 13px !important;
7506
+ }
7507
+
7508
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-message {
7509
+ font-size: 13px !important;
7510
+ line-height: 1.25 !important;
7511
+ }
7512
+
7513
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-meta {
7514
+ gap: 8px !important;
7515
+ font-size: 11px !important;
7516
+ line-height: 1.25 !important;
7517
+ }
7518
+
7519
+ .swal2-popup.pinokio-history-modal .pinokio-git-commit-hash {
7520
+ border-radius: 4px !important;
7521
+ padding: 1px 6px !important;
7522
+ }
7523
+
7524
+ .pinokio-modal-checkbox-row input[type="checkbox"] {
7525
+ accent-color: var(--pinokio-modal-title-color) !important;
7526
+ }
7527
+
7528
+ .pinokio-custom-commit-modal,
7529
+ .pinokio-custom-terminal-modal,
7530
+ body.dark .pinokio-custom-commit-modal,
7531
+ body.dark .pinokio-custom-terminal-modal {
7532
+ background: var(--pinokio-custom-commit-modal-bg) !important;
7533
+ color: var(--pinokio-custom-commit-modal-text) !important;
7534
+ border: 1px solid var(--pinokio-custom-commit-border) !important;
7535
+ border-radius: 8px !important;
7536
+ box-shadow: var(--pinokio-modern-shadow) !important;
7537
+ }
7538
+
7539
+ .pinokio-custom-commit-header,
7540
+ .pinokio-custom-terminal-header,
7541
+ body.dark .pinokio-custom-commit-header,
7542
+ body.dark .pinokio-custom-terminal-header {
7543
+ background: var(--pinokio-custom-commit-header-bg) !important;
7544
+ border-bottom: 1px solid var(--pinokio-custom-commit-border) !important;
7545
+ padding: 14px 16px !important;
7546
+ }
7547
+
7548
+ .pinokio-custom-commit-close,
7549
+ .pinokio-custom-terminal-close {
7550
+ width: 28px !important;
7551
+ height: 28px !important;
7552
+ padding: 0 !important;
7553
+ border-radius: 6px !important;
7554
+ color: var(--pinokio-custom-commit-close-color) !important;
7555
+ }
7556
+
7557
+ .pinokio-custom-commit-close:hover,
7558
+ .pinokio-custom-terminal-close:hover {
7559
+ background: var(--pinokio-custom-commit-close-hover-bg) !important;
7560
+ color: var(--pinokio-custom-commit-close-hover-color) !important;
7561
+ }
7562
+
7563
+ @media (max-width: 520px) {
7564
+ .pinokio-modern-modal.swal2-popup,
7565
+ .pinokio-no-changes-popup.swal2-popup {
7566
+ width: calc(100vw - 24px) !important;
7567
+ }
7568
+
7569
+ .pinokio-modal-header {
7570
+ padding: 12px !important;
6691
7571
  }
6692
- .appcanvas.community-mode .browserview-shell {
6693
- flex: 1 1 auto;
7572
+
7573
+ .pinokio-github-login {
7574
+ padding: 20px 16px 16px !important;
6694
7575
  }
6695
7576
  }
6696
7577
  </style>
@@ -6865,9 +7746,6 @@ header.navheader h1 {
6865
7746
  <button type='button' id='menu-mobile-close' class='btn mobile-sheet-action' data-tippy-content="Close menu" aria-label="Close menu" title="Close menu">
6866
7747
  <i class="fa-solid fa-xmark"></i>
6867
7748
  </button>
6868
- <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
6869
- <i class="fa-solid fa-house"></i>
6870
- </a>
6871
7749
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
6872
7750
  <i class="fa-solid fa-rotate-right"></i>
6873
7751
  </button>
@@ -6912,8 +7790,8 @@ header.navheader h1 {
6912
7790
  </div>
6913
7791
  </div>
6914
7792
  <% } %>
6915
- <%if (type === 'run') { %>
6916
- <div class='m h menu' data-type='h'>
7793
+ <%if (type === 'run') { %>
7794
+ <div class='m h menu' data-type='h'>
6917
7795
  <% if (config.menu) { %>
6918
7796
  <%- include('./partials/menu', { menu: config.menu, }) %>
6919
7797
  <% } %>
@@ -6924,9 +7802,9 @@ header.navheader h1 {
6924
7802
  <div class='flexible'></div>
6925
7803
  </div>
6926
7804
  </a>
6927
- </div>
6928
- <% } %>
6929
- <div class='m s temp-menu' data-type='s'>
7805
+ </div>
7806
+ <% } %>
7807
+ <div class='m s temp-menu' data-type='s'>
6930
7808
  <%tabs.forEach((tab, i) => { %>
6931
7809
  <% const tabHref = typeof tab === "string" ? tab : ((tab && typeof tab.href === "string") ? tab.href : "") %>
6932
7810
  <% const tabLabel = typeof tab === "string" ? tab : ((tab && typeof tab.label === "string" && tab.label.trim().length > 0) ? tab.label.trim() : tabHref) %>
@@ -6937,10 +7815,44 @@ header.navheader h1 {
6937
7815
  <i class="fa-solid fa-link"></i><div class='display'><%=tabLabel%></div><div class='flexible'></div><% if (!tabIsShell) { %><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button><% } %>
6938
7816
  </div>
6939
7817
  </a>
6940
- <%})%>
6941
- </div>
6942
- </div>
6943
- <div class='menu-actions <%= type === "browse" ? "dev-menu-actions" : "" %>'>
7818
+ <%})%>
7819
+ </div>
7820
+ </div>
7821
+ <div class='mobile-drawer-actions' aria-label="App actions">
7822
+ <button type='button' class='btn header-item mobile-nav-logs' data-mobile-proxy="#logs-toggle" data-mobile-panel="logs" data-mobile-close-menu="true" aria-pressed="false" aria-label="Logs">
7823
+ <div class='tab'>
7824
+ <i class="fa-solid fa-laptop-code menu-action-leading-icon"></i>
7825
+ <div class='display'>Logs</div>
7826
+ <div class='flexible'></div>
7827
+ </div>
7828
+ </button>
7829
+ <% if (type === 'run') { %>
7830
+ <button type='button' class='btn header-item mobile-nav-ask-ai' data-mobile-proxy="#ask-ai-tab" data-mobile-panel="ask-ai" data-mobile-close-menu="true" aria-pressed="false" aria-label="Ask AI">
7831
+ <div class='tab'>
7832
+ <span class="ask-ai-brand-icon menu-action-leading-icon" aria-hidden="true"></span>
7833
+ <div class='display'>Ask AI</div>
7834
+ <div class='flexible'></div>
7835
+ </div>
7836
+ </button>
7837
+ <% } %>
7838
+ <% if (registryEnabled) { %>
7839
+ <button type='button' class='btn header-item mobile-nav-community' data-mobile-proxy="#community-mode-toggle" data-mobile-panel="feed" data-mobile-close-menu="true" aria-pressed="false" aria-label="Project feed">
7840
+ <div class='tab'>
7841
+ <i class="fa-solid fa-rss menu-action-leading-icon"></i>
7842
+ <div class='display'>Feed</div>
7843
+ <div class='flexible'></div>
7844
+ </div>
7845
+ </button>
7846
+ <% } %>
7847
+ <a class='btn header-item mobile-drawer-home' href="/home" aria-label="Home">
7848
+ <div class='tab'>
7849
+ <i class="fa-solid fa-house menu-action-leading-icon"></i>
7850
+ <div class='display'>Home</div>
7851
+ <div class='flexible'></div>
7852
+ </div>
7853
+ </a>
7854
+ </div>
7855
+ <div class='menu-actions <%= type === "browse" ? "dev-menu-actions" : "" %>'>
6944
7856
  <% if (type === 'browse') { %>
6945
7857
  <%- include('./partials/fs_status') %>
6946
7858
  <% } %>
@@ -7070,6 +7982,7 @@ header.navheader h1 {
7070
7982
  <% if (type === 'files') { %>
7071
7983
  <iframe class='selected' src="<%=editor_tab%>" allow="fullscreen *;" allowfullscreen></iframe>
7072
7984
  <% } %>
7985
+ <div id="browserview-network-status" class="browserview-network-status" hidden aria-live="polite"></div>
7073
7986
  <%- include('./partials/browser_popout_surface') %>
7074
7987
  </main>
7075
7988
  <% if (type === 'run') { %>
@@ -7256,6 +8169,7 @@ header.navheader h1 {
7256
8169
  </div>
7257
8170
  <% } %>
7258
8171
  </div>
8172
+ <button type='button' class='mobile-menu-backdrop' data-mobile-menu-backdrop aria-label="Close Pinokio menu" hidden></button>
7259
8173
  <nav class='mobile-bottom-nav' aria-label="Mobile navigation">
7260
8174
  <button type='button' class='btn2 mobile-bottom-nav__button mobile-nav-menu' data-mobile-proxy="#menu-mobile" aria-expanded="false" aria-label="Open Pinokio menu">
7261
8175
  <img class='mobile-bottom-nav__logo' src="/pinokio-black.png" alt="" aria-hidden="true">
@@ -7266,14 +8180,14 @@ header.navheader h1 {
7266
8180
  <% } %>
7267
8181
  <span class='mobile-bottom-nav__identity-title'><%=config.title || name%></span>
7268
8182
  <span class='mobile-bottom-nav__identity-separator' aria-hidden="true"></span>
7269
- <div class="resource-usage" data-resource-usage-root data-workspace="<%=name%>">
8183
+ <div class="resource-usage" data-resource-usage-root data-resource-always-visible="true" data-workspace="<%=name%>">
7270
8184
  <button type="button" class="resource-usage-trigger" data-resource-usage-trigger aria-haspopup="dialog" aria-expanded="false" aria-label="Resource usage">
7271
8185
  <span class="resource-chip resource-chip--disk">
7272
8186
  <span class="disk-usage mobile-bottom-nav__identity-disk" data-path="/" data-filepath="<%=path%>" data-metric-label="Disk">--</span>
7273
8187
  </span>
7274
- <span class="resource-chip resource-chip--cpu hidden" data-resource-chip="cpu">CPU --</span>
7275
- <span class="resource-chip resource-chip--ram hidden" data-resource-chip="ram">RAM --</span>
7276
- <span class="resource-chip resource-chip--vram hidden" data-resource-chip="vram">VRAM --</span>
8188
+ <span class="resource-chip resource-chip--cpu" data-resource-chip="cpu">CPU --</span>
8189
+ <span class="resource-chip resource-chip--ram" data-resource-chip="ram">RAM --</span>
8190
+ <span class="resource-chip resource-chip--vram" data-resource-chip="vram">VRAM --</span>
7277
8191
  </button>
7278
8192
  <div class="resource-usage-popover hidden" data-resource-usage-popover role="dialog" aria-label="Resource usage settings">
7279
8193
  <div class="resource-usage-popover-head">Resources</div>
@@ -7293,19 +8207,6 @@ header.navheader h1 {
7293
8207
  </div>
7294
8208
  </div>
7295
8209
  </div>
7296
- <% if (registryEnabled) { %>
7297
- <button type='button' class='btn2 mobile-bottom-nav__button mobile-nav-community' data-mobile-proxy="#community-mode-toggle" data-mobile-close-menu="true" aria-pressed="false" aria-label="Project feed">
7298
- <i class="fa-solid fa-rss"></i>
7299
- </button>
7300
- <% } %>
7301
- <button type='button' class='btn2 mobile-bottom-nav__button mobile-nav-logs' data-mobile-proxy="#logs-toggle" data-mobile-close-menu="true" aria-pressed="false" aria-label="Logs">
7302
- <i class="fa-solid fa-laptop-code"></i>
7303
- </button>
7304
- <% if (type === 'run') { %>
7305
- <button type='button' class='btn2 mobile-bottom-nav__button mobile-nav-ask-ai' data-mobile-proxy="#ask-ai-tab" data-mobile-close-menu="true" aria-pressed="false" aria-label="Ask AI">
7306
- <span class="ask-ai-brand-icon" aria-hidden="true"></span>
7307
- </button>
7308
- <% } %>
7309
8210
  </nav>
7310
8211
  </div>
7311
8212
  <div class='mobile-menu-fallback' aria-hidden="true">
@@ -7328,9 +8229,6 @@ header.navheader h1 {
7328
8229
  </a>
7329
8230
  </div>
7330
8231
  <div class='mobile-sheet-actions' aria-label="Workspace actions">
7331
- <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
7332
- <i class="fa-solid fa-house"></i>
7333
- </a>
7334
8232
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
7335
8233
  <i class="fa-solid fa-rotate-right"></i>
7336
8234
  </button>
@@ -7353,6 +8251,31 @@ header.navheader h1 {
7353
8251
  <i class="fa-solid fa-xmark"></i>
7354
8252
  </button>
7355
8253
  </div>
8254
+ <div class='mobile-drawer-actions' aria-label="App actions">
8255
+ <button type='button' class='btn header-item mobile-nav-logs' data-mobile-proxy="#fs-status .fs-logs .fs-status-btn" data-mobile-panel="logs" data-mobile-close-menu="true" aria-pressed="false" aria-label="Logs">
8256
+ <div class='tab'>
8257
+ <i class="fa-solid fa-laptop-code menu-action-leading-icon"></i>
8258
+ <div class='display'>Logs</div>
8259
+ <div class='flexible'></div>
8260
+ </div>
8261
+ </button>
8262
+ <% if (registryEnabled) { %>
8263
+ <button type='button' class='btn header-item mobile-nav-community' data-mobile-proxy="#community-mode-toggle" data-mobile-panel="feed" data-mobile-close-menu="true" aria-pressed="false" aria-label="Project feed">
8264
+ <div class='tab'>
8265
+ <i class="fa-solid fa-rss menu-action-leading-icon"></i>
8266
+ <div class='display'>Feed</div>
8267
+ <div class='flexible'></div>
8268
+ </div>
8269
+ </button>
8270
+ <% } %>
8271
+ <a class='btn header-item mobile-drawer-home' href="/home" aria-label="Home">
8272
+ <div class='tab'>
8273
+ <i class="fa-solid fa-house menu-action-leading-icon"></i>
8274
+ <div class='display'>Home</div>
8275
+ <div class='flexible'></div>
8276
+ </div>
8277
+ </a>
8278
+ </div>
7356
8279
  </div>
7357
8280
  </div>
7358
8281
  <script>
@@ -7419,6 +8342,95 @@ header.navheader h1 {
7419
8342
  let initialHomeSelectionRetries = 0
7420
8343
  let ignorePersistedSelection = pluginLaunchActive || Boolean(initialHomeSelectionPayload)
7421
8344
  let lastForegroundSignature = null
8345
+ let networkSharingWarningOpen = false
8346
+ let pendingNetworkSharingSelectionRetry = null
8347
+ const networkSharingSelectionRetries = new Map()
8348
+ let networkSharingStatusRequest = null
8349
+ const NETWORK_SHARING_SELECTION_RETRY_LIMIT = 30
8350
+ const scheduleNetworkSharingSelectionRetry = (delay = 1000) => {
8351
+ if (pendingNetworkSharingSelectionRetry !== null) {
8352
+ return
8353
+ }
8354
+ pendingNetworkSharingSelectionRetry = setTimeout(() => {
8355
+ pendingNetworkSharingSelectionRetry = null
8356
+ refresh(false, { nodelay: true })
8357
+ }, delay)
8358
+ }
8359
+ const cancelNetworkSharingSelectionRetry = () => {
8360
+ if (pendingNetworkSharingSelectionRetry !== null) {
8361
+ clearTimeout(pendingNetworkSharingSelectionRetry)
8362
+ pendingNetworkSharingSelectionRetry = null
8363
+ }
8364
+ }
8365
+ const isLoopbackHost = (hostname) => {
8366
+ const normalized = String(hostname || "").toLowerCase()
8367
+ return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1" || normalized === "[::1]"
8368
+ }
8369
+ const requiresNetworkSharing = (href) => {
8370
+ if (isLoopbackHost(window.location.hostname)) {
8371
+ return false
8372
+ }
8373
+ try {
8374
+ const parsed = new URL(href, window.location.href)
8375
+ return parsed.protocol === "http:" && isLoopbackHost(parsed.hostname)
8376
+ } catch (_) {
8377
+ return false
8378
+ }
8379
+ }
8380
+ const isNetworkSharedHref = (href) => {
8381
+ if (isLoopbackHost(window.location.hostname)) {
8382
+ return false
8383
+ }
8384
+ try {
8385
+ const parsed = new URL(href, window.location.href)
8386
+ const page = new URL(window.location.href)
8387
+ return parsed.protocol === "http:" && parsed.hostname === page.hostname && parsed.port && parsed.port !== page.port
8388
+ } catch (_) {
8389
+ return false
8390
+ }
8391
+ }
8392
+ const canLoadNetworkSharedHref = async (href, timeout = 750) => {
8393
+ if (!isNetworkSharedHref(href)) {
8394
+ return true
8395
+ }
8396
+ if (typeof AbortController !== "function") {
8397
+ return true
8398
+ }
8399
+ const controller = new AbortController()
8400
+ const timer = setTimeout(() => {
8401
+ controller.abort()
8402
+ }, timeout)
8403
+ try {
8404
+ await fetch(href, { cache: "no-store", mode: "no-cors", signal: controller.signal })
8405
+ return true
8406
+ } catch (_) {
8407
+ return false
8408
+ } finally {
8409
+ clearTimeout(timer)
8410
+ }
8411
+ }
8412
+ const showNetworkSharingRequired = (href) => {
8413
+ if (!requiresNetworkSharing(href)) {
8414
+ return false
8415
+ }
8416
+ if (networkSharingWarningOpen) {
8417
+ return true
8418
+ }
8419
+ networkSharingWarningOpen = true
8420
+ Swal.fire({
8421
+ title: "Turn on network sharing",
8422
+ text: "Open Network to turn on local network sharing, then come back to this app.",
8423
+ showCancelButton: true,
8424
+ confirmButtonText: "Open Network",
8425
+ cancelButtonText: "Stay here"
8426
+ }).then((result) => {
8427
+ networkSharingWarningOpen = false
8428
+ if (result.isConfirmed) {
8429
+ window.location.href = "/network"
8430
+ }
8431
+ })
8432
+ return true
8433
+ }
7422
8434
  const browserPopoutSurface = window.createBrowserPopoutSurface({
7423
8435
  onShow: () => {
7424
8436
  lastForegroundSignature = null
@@ -7560,6 +8572,10 @@ header.navheader h1 {
7560
8572
  frame.setAttribute("data-pinokio-inject", serialized)
7561
8573
  }
7562
8574
  const create_iframe = (name, href, injectDescriptors = []) => {
8575
+ if (showNetworkSharingRequired(href)) {
8576
+ return
8577
+ }
8578
+ clearBrowserviewNetworkStatus()
7563
8579
  document.querySelectorAll(".menu-container .selected").forEach((el) => {
7564
8580
  el.classList.remove("selected")
7565
8581
  })
@@ -7645,6 +8661,113 @@ header.navheader h1 {
7645
8661
  }
7646
8662
  })
7647
8663
  }
8664
+ const NETWORK_STATUS_SPINNER_HTML = `
8665
+ <span class="install-status-spinner" aria-hidden="true">
8666
+ <span class="install-status-grid-anchor install-status-grid-anchor-1"></span>
8667
+ <span class="install-status-grid-anchor install-status-grid-anchor-2"></span>
8668
+ <span class="install-status-grid-anchor install-status-grid-anchor-3"></span>
8669
+ <span class="install-status-grid-anchor install-status-grid-anchor-4"></span>
8670
+ <span class="install-status-grid-chaser"></span>
8671
+ </span>`
8672
+ const browserviewNetworkStatusElement = () => {
8673
+ return document.getElementById("browserview-network-status")
8674
+ }
8675
+ const formatNetworkStatusRoute = (href) => {
8676
+ try {
8677
+ const parsed = new URL(href, window.location.href)
8678
+ const targetHost = `${parsed.hostname}${parsed.port ? `:${parsed.port}` : ""}`
8679
+ if (requiresNetworkSharing(href)) {
8680
+ return `${targetHost} -> ${window.location.hostname}`
8681
+ }
8682
+ if (isNetworkSharedHref(href)) {
8683
+ return targetHost
8684
+ }
8685
+ } catch (_) {}
8686
+ return ""
8687
+ }
8688
+ const clearBrowserviewNetworkStatus = () => {
8689
+ const status = browserviewNetworkStatusElement()
8690
+ if (status) {
8691
+ status.hidden = true
8692
+ status.dataset.state = "waiting"
8693
+ status.innerHTML = ""
8694
+ }
8695
+ cancelNetworkSharingSelectionRetry()
8696
+ networkSharingSelectionRetries.clear()
8697
+ }
8698
+ const setBrowserviewNetworkStatus = ({ state = "waiting", title = "", detail = "", route = "", actions = false } = {}) => {
8699
+ const status = browserviewNetworkStatusElement()
8700
+ if (!status) {
8701
+ return
8702
+ }
8703
+ status.hidden = false
8704
+ status.dataset.state = state
8705
+ status.dataset.installSpinnerVariant = "corner-chase"
8706
+ const spinnerHtml = state === "waiting" ? NETWORK_STATUS_SPINNER_HTML : ""
8707
+ const routeHtml = route ? `<div class="browserview-network-status-route">${escapeTabHtml(route)}</div>` : ""
8708
+ const actionsHtml = actions ? `
8709
+ <div class="browserview-network-status-actions">
8710
+ <button type="button" class="btn2 browserview-network-status-primary" data-network-status-action="network">
8711
+ <span>Set Up</span>
8712
+ </button>
8713
+ <button type="button" class="btn2 browserview-network-status-secondary" data-network-status-action="cancel">
8714
+ <span>Cancel</span>
8715
+ </button>
8716
+ </div>` : ""
8717
+ status.innerHTML = `
8718
+ <div class="browserview-network-status-inner">
8719
+ ${spinnerHtml}
8720
+ <div class="browserview-network-status-title">${escapeTabHtml(title)}</div>
8721
+ <div class="browserview-network-status-detail">${escapeTabHtml(detail)}</div>
8722
+ ${routeHtml}
8723
+ ${actionsHtml}
8724
+ </div>`
8725
+ const networkButton = status.querySelector('[data-network-status-action="network"]')
8726
+ if (networkButton) {
8727
+ networkButton.addEventListener("click", (event) => {
8728
+ event.preventDefault()
8729
+ event.stopPropagation()
8730
+ window.location.href = "/network"
8731
+ })
8732
+ }
8733
+ const cancelButton = status.querySelector('[data-network-status-action="cancel"]')
8734
+ if (cancelButton) {
8735
+ cancelButton.addEventListener("click", (event) => {
8736
+ event.preventDefault()
8737
+ event.stopPropagation()
8738
+ clearBrowserviewNetworkStatus()
8739
+ })
8740
+ }
8741
+ }
8742
+ const queryNetworkSharingStatus = async () => {
8743
+ if (networkSharingStatusRequest) {
8744
+ return networkSharingStatusRequest
8745
+ }
8746
+ networkSharingStatusRequest = fetch("/info/network-sharing", { cache: "no-store" })
8747
+ .then(async (response) => {
8748
+ if (!response.ok) {
8749
+ throw new Error(`network sharing status failed: ${response.status}`)
8750
+ }
8751
+ return response.json()
8752
+ })
8753
+ .catch(() => null)
8754
+ .finally(() => {
8755
+ networkSharingStatusRequest = null
8756
+ })
8757
+ return networkSharingStatusRequest
8758
+ }
8759
+ const networkSharingBlockedDetail = (status) => {
8760
+ if (!status) {
8761
+ return null
8762
+ }
8763
+ if (status.installed === false) {
8764
+ return "Network sharing has not finished setup. Set it up, then come back to this app."
8765
+ }
8766
+ if (status.active === false) {
8767
+ return "Network sharing is turned off. Set it up, then come back to this app."
8768
+ }
8769
+ return null
8770
+ }
7648
8771
  const previewClass = "tab-preview"
7649
8772
  const tabMainClass = "tab-main"
7650
8773
  const tabDetailsClass = "tab-details"
@@ -9023,6 +10146,7 @@ const rerenderMenuSection = (container, html) => {
9023
10146
  }
9024
10147
 
9025
10148
  if (!target) {
10149
+ clearBrowserviewNetworkStatus()
9026
10150
  syncActiveNestedPath()
9027
10151
  if (typeof syncLogsSelectedState === "function") {
9028
10152
  syncLogsSelectedState(null)
@@ -9033,15 +10157,92 @@ const rerenderMenuSection = (container, html) => {
9033
10157
  return
9034
10158
  }
9035
10159
 
9036
- document.querySelector(".container").classList.add("active")
9037
- document.querySelector("aside").classList.remove("active")
10160
+ document.querySelector(".container").classList.add("active")
10161
+ document.querySelector("aside").classList.remove("active")
9038
10162
 
9039
10163
 
9040
- // Instantiate a frame with the selected target's href
9041
- const targetInjectDescriptors = readLinkInjectDescriptors(target)
9042
- if (!target.href) {
9043
- return
9044
- }
10164
+ // Instantiate a frame with the selected target's href
10165
+ const targetInjectDescriptors = readLinkInjectDescriptors(target)
10166
+ if (!target.href) {
10167
+ return
10168
+ }
10169
+ const automaticDefaultSelection = target.hasAttribute('data-default') && !(eventParam && eventParam.isTrusted)
10170
+ const networkSharingRetryKey = target.getAttribute("target") || target.href
10171
+ if (automaticDefaultSelection && requiresNetworkSharing(target.href)) {
10172
+ const route = formatNetworkStatusRoute(target.href)
10173
+ const retries = networkSharingSelectionRetries.get(networkSharingRetryKey) || 0
10174
+ if (retries === 0) {
10175
+ setBrowserviewNetworkStatus({
10176
+ state: "waiting",
10177
+ title: "Opening Web UI",
10178
+ detail: "Checking network sharing...",
10179
+ route
10180
+ })
10181
+ const status = await queryNetworkSharingStatus()
10182
+ const blockedDetail = networkSharingBlockedDetail(status)
10183
+ if (blockedDetail) {
10184
+ networkSharingSelectionRetries.delete(networkSharingRetryKey)
10185
+ setBrowserviewNetworkStatus({
10186
+ state: "blocked",
10187
+ title: "Network sharing is not ready",
10188
+ detail: blockedDetail,
10189
+ route,
10190
+ actions: true
10191
+ })
10192
+ return
10193
+ }
10194
+ }
10195
+ if (retries < NETWORK_SHARING_SELECTION_RETRY_LIMIT) {
10196
+ networkSharingSelectionRetries.set(networkSharingRetryKey, retries + 1)
10197
+ setBrowserviewNetworkStatus({
10198
+ state: "waiting",
10199
+ title: "Opening Web UI",
10200
+ detail: "Waiting for the network sharing route...",
10201
+ route
10202
+ })
10203
+ scheduleNetworkSharingSelectionRetry()
10204
+ return
10205
+ }
10206
+ setBrowserviewNetworkStatus({
10207
+ state: "blocked",
10208
+ title: "Network sharing is not ready",
10209
+ detail: "The local app is running, but Pinokio has not created a network route for this Web UI yet.",
10210
+ route,
10211
+ actions: true
10212
+ })
10213
+ return
10214
+ }
10215
+ if (automaticDefaultSelection && isNetworkSharedHref(target.href) && !(await canLoadNetworkSharedHref(target.href))) {
10216
+ const route = formatNetworkStatusRoute(target.href)
10217
+ const retries = networkSharingSelectionRetries.get(networkSharingRetryKey) || 0
10218
+ if (retries < NETWORK_SHARING_SELECTION_RETRY_LIMIT) {
10219
+ networkSharingSelectionRetries.set(networkSharingRetryKey, retries + 1)
10220
+ setBrowserviewNetworkStatus({
10221
+ state: "waiting",
10222
+ title: "Opening Web UI",
10223
+ detail: "Waiting for the Web UI to respond...",
10224
+ route
10225
+ })
10226
+ scheduleNetworkSharingSelectionRetry()
10227
+ return
10228
+ }
10229
+ setBrowserviewNetworkStatus({
10230
+ state: "blocked",
10231
+ title: "Web UI is not responding",
10232
+ detail: "Pinokio created the network route, but the Web UI did not respond yet.",
10233
+ route,
10234
+ actions: true
10235
+ })
10236
+ return
10237
+ }
10238
+ clearBrowserviewNetworkStatus()
10239
+ if (showNetworkSharingRequired(target.href)) {
10240
+ if (eventParam) {
10241
+ eventParam.preventDefault()
10242
+ eventParam.stopPropagation()
10243
+ }
10244
+ return
10245
+ }
9045
10246
  //document.querySelector("#location").value = url
9046
10247
 
9047
10248
  // document.querySelector("#open-location").setAttribute('href', target.href)
@@ -9565,6 +10766,9 @@ const rerenderMenuSection = (container, html) => {
9565
10766
  }
9566
10767
  window.PinokioOpenLogsPage = async (options = {}) => {
9567
10768
  const view = options && options.view === "raw" ? "raw" : "latest"
10769
+ if (window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
10770
+ await window.PinokioCloseOtherMobilePanels("logs")
10771
+ }
9568
10772
  const relativeUrl = buildEmbeddedLogsUrl(view)
9569
10773
  const existingLink = Array.from(document.querySelectorAll('.temp-menu .frame-link')).find(isLogsLink)
9570
10774
  rememberNonLogsSelection(document.querySelector(".frame-link.selected"))
@@ -9829,21 +11033,68 @@ const rerenderMenuSection = (container, html) => {
9829
11033
 
9830
11034
 
9831
11035
 
9832
- const mobileMenuQuery = window.matchMedia ? window.matchMedia("(max-width: 768px)") : null
9833
- const isMobileMenuOpen = () => document.body.classList.contains("mobile-menu-open")
9834
- const appcanvas = document.querySelector(".appcanvas")
9835
- const closeWindowButton = document.querySelector("#close-window")
9836
- const syncMobileBottomNavState = () => {
9837
- const mobileMenuOpen = isMobileMenuOpen()
9838
- const communityModeActive = !!(appcanvas && appcanvas.classList.contains("community-mode"))
11036
+ const mobileMenuQuery = window.matchMedia ? window.matchMedia("(max-width: 768px)") : null
11037
+ const isMobileMenuOpen = () => document.body.classList.contains("mobile-menu-open")
11038
+ const appcanvas = document.querySelector(".appcanvas")
11039
+ const closeWindowButton = document.querySelector("#close-window")
11040
+ const mobileMenuBackdrop = document.querySelector("[data-mobile-menu-backdrop]")
11041
+ const isMobilePanelLayout = () => mobileMenuQuery ? mobileMenuQuery.matches : window.innerWidth <= 768
11042
+ const normalizeMobilePanelName = (value) => {
11043
+ return value === "logs" || value === "ask-ai" || value === "feed" ? value : ""
11044
+ }
11045
+ const closeOtherMobilePanels = async (activePanel) => {
11046
+ const panel = normalizeMobilePanelName(activePanel)
11047
+ if (!panel || !isMobilePanelLayout()) {
11048
+ return
11049
+ }
11050
+ if (panel !== "ask-ai") {
11051
+ const askAiDrawer = window.PinokioAskAiDrawer
11052
+ if (askAiDrawer && typeof askAiDrawer.close === "function") {
11053
+ askAiDrawer.close()
11054
+ }
11055
+ }
11056
+ if (panel !== "feed") {
11057
+ const communityDrawer = window.PinokioCommunityDrawer
11058
+ if (communityDrawer && typeof communityDrawer.closeMobileMode === "function") {
11059
+ communityDrawer.closeMobileMode()
11060
+ } else if (appcanvas && appcanvas.classList.contains("community-mode")) {
11061
+ const communityModeButton = document.getElementById("community-mode-toggle")
11062
+ if (communityModeButton) {
11063
+ communityModeButton.click()
11064
+ }
11065
+ }
11066
+ }
11067
+ if (panel !== "logs") {
11068
+ const logsDrawer = window.PinokioLogsDrawer
11069
+ if (logsDrawer && typeof logsDrawer.close === "function") {
11070
+ logsDrawer.close()
11071
+ }
11072
+ if (
11073
+ window.PinokioIsLogsPageSelected &&
11074
+ typeof window.PinokioIsLogsPageSelected === "function" &&
11075
+ window.PinokioIsLogsPageSelected() &&
11076
+ window.PinokioCloseLogsPage &&
11077
+ typeof window.PinokioCloseLogsPage === "function"
11078
+ ) {
11079
+ await window.PinokioCloseLogsPage()
11080
+ }
11081
+ }
11082
+ }
11083
+ window.PinokioCloseOtherMobilePanels = closeOtherMobilePanels
11084
+ const syncMobileBottomNavState = () => {
11085
+ const mobileMenuOpen = isMobileMenuOpen()
11086
+ const communityModeActive = !!(appcanvas && appcanvas.classList.contains("community-mode"))
9839
11087
  const askAiOpen = !!(appcanvas && appcanvas.classList.contains("panel-open"))
9840
11088
  const mobileMenuFallback = document.querySelector(".mobile-menu-fallback")
9841
11089
  const closeSectionVisible = !!(closeWindowButton && !closeWindowButton.classList.contains("hidden"))
9842
11090
 
9843
- document.querySelectorAll(".mobile-nav-menu").forEach((button) => {
9844
- button.classList.toggle("selected", mobileMenuOpen)
9845
- button.setAttribute("aria-expanded", mobileMenuOpen ? "true" : "false")
9846
- })
11091
+ document.querySelectorAll(".mobile-nav-menu").forEach((button) => {
11092
+ button.classList.toggle("selected", mobileMenuOpen)
11093
+ button.setAttribute("aria-expanded", mobileMenuOpen ? "true" : "false")
11094
+ })
11095
+ if (mobileMenuBackdrop) {
11096
+ mobileMenuBackdrop.hidden = !mobileMenuOpen
11097
+ }
9847
11098
  document.querySelectorAll(".mobile-nav-community").forEach((button) => {
9848
11099
  button.classList.toggle("selected", communityModeActive)
9849
11100
  button.setAttribute("aria-pressed", communityModeActive ? "true" : "false")
@@ -9864,26 +11115,29 @@ const rerenderMenuSection = (container, html) => {
9864
11115
  mobileMenuFallback.setAttribute("aria-hidden", showFallback ? "false" : "true")
9865
11116
  }
9866
11117
  }
9867
- const setMobileMenuOpen = (next, options = {}) => {
9868
- const shouldOpen = !!next
9869
- if (!mobileMenuQuery || !mobileMenuQuery.matches) {
9870
- document.body.classList.remove("mobile-menu-open")
9871
- syncMobileBottomNavState()
9872
- return
9873
- }
9874
- document.body.classList.toggle("mobile-menu-open", shouldOpen)
9875
- if (shouldOpen && !options.skipRefresh) {
9876
- refresh(false, { nodelay: true })
9877
- }
11118
+ const setMobileMenuOpen = (next, options = {}) => {
11119
+ const shouldOpen = !!next
11120
+ if (!mobileMenuQuery || !mobileMenuQuery.matches) {
11121
+ document.body.classList.remove("mobile-menu-open")
11122
+ document.documentElement.classList.remove("mobile-menu-open")
11123
+ syncMobileBottomNavState()
11124
+ return
11125
+ }
11126
+ document.body.classList.toggle("mobile-menu-open", shouldOpen)
11127
+ document.documentElement.classList.toggle("mobile-menu-open", shouldOpen)
11128
+ if (shouldOpen && !options.skipRefresh) {
11129
+ refresh(false, { nodelay: true })
11130
+ }
9878
11131
  syncMobileBottomNavState()
9879
11132
  }
9880
11133
 
9881
- const handleMobileMenuQueryChange = () => {
9882
- if (!mobileMenuQuery || !mobileMenuQuery.matches) {
9883
- document.body.classList.remove("mobile-menu-open")
9884
- }
9885
- syncMobileBottomNavState()
9886
- }
11134
+ const handleMobileMenuQueryChange = () => {
11135
+ if (!mobileMenuQuery || !mobileMenuQuery.matches) {
11136
+ document.body.classList.remove("mobile-menu-open")
11137
+ document.documentElement.classList.remove("mobile-menu-open")
11138
+ }
11139
+ syncMobileBottomNavState()
11140
+ }
9887
11141
  if (mobileMenuQuery && typeof mobileMenuQuery.addEventListener === "function") {
9888
11142
  mobileMenuQuery.addEventListener("change", handleMobileMenuQueryChange)
9889
11143
  } else if (mobileMenuQuery && typeof mobileMenuQuery.addListener === "function") {
@@ -9899,14 +11153,19 @@ const rerenderMenuSection = (container, html) => {
9899
11153
  setMobileMenuOpen(!isMobileMenuOpen())
9900
11154
  })
9901
11155
  }
9902
- if (document.querySelector("#menu-mobile-close")) {
9903
- document.querySelector("#menu-mobile-close").addEventListener("click", (e) => {
9904
- e.preventDefault()
9905
- setMobileMenuOpen(false, { skipRefresh: true })
9906
- })
9907
- }
9908
- document.querySelectorAll("[data-mobile-proxy]").forEach((trigger) => {
9909
- trigger.addEventListener("click", (event) => {
11156
+ if (document.querySelector("#menu-mobile-close")) {
11157
+ document.querySelector("#menu-mobile-close").addEventListener("click", (e) => {
11158
+ e.preventDefault()
11159
+ setMobileMenuOpen(false, { skipRefresh: true })
11160
+ })
11161
+ }
11162
+ if (mobileMenuBackdrop) {
11163
+ mobileMenuBackdrop.addEventListener("click", () => {
11164
+ setMobileMenuOpen(false, { skipRefresh: true })
11165
+ })
11166
+ }
11167
+ document.querySelectorAll("[data-mobile-proxy]").forEach((trigger) => {
11168
+ trigger.addEventListener("click", async (event) => {
9910
11169
  const selector = trigger.getAttribute("data-mobile-proxy")
9911
11170
  if (!selector) {
9912
11171
  return
@@ -9919,10 +11178,16 @@ const rerenderMenuSection = (container, html) => {
9919
11178
  if (trigger.getAttribute("data-mobile-close-menu") === "true" && isMobileMenuOpen()) {
9920
11179
  setMobileMenuOpen(false, { skipRefresh: true })
9921
11180
  }
11181
+ await closeOtherMobilePanels(trigger.getAttribute("data-mobile-panel"))
9922
11182
  target.click()
9923
- setTimeout(syncMobileBottomNavState, 0)
9924
- })
9925
- })
11183
+ setTimeout(syncMobileBottomNavState, 0)
11184
+ })
11185
+ })
11186
+ document.addEventListener("keydown", (event) => {
11187
+ if (event.key === "Escape" && isMobileMenuOpen()) {
11188
+ setMobileMenuOpen(false, { skipRefresh: true })
11189
+ }
11190
+ })
9926
11191
  if (appcanvas && typeof MutationObserver === "function") {
9927
11192
  const mobileNavObserver = new MutationObserver(() => {
9928
11193
  syncMobileBottomNavState()
@@ -10888,11 +12153,13 @@ const rerenderMenuSection = (container, html) => {
10888
12153
  refresh()
10889
12154
  }
10890
12155
  } else {
12156
+ const launchLink = getTabLink(rawName) || findFrameLinkByTarget(rawName)
12157
+ const launchHref = launchLink && launchLink.href && requiresNetworkSharing(event.data.launch.href) && !requiresNetworkSharing(launchLink.href) ? launchLink.href : event.data.launch.href
10891
12158
  const frameExists = Array.from(document.querySelectorAll("main.browserview iframe")).some((frame) => {
10892
12159
  return frame.name === rawName
10893
12160
  })
10894
12161
  if (!frameExists) {
10895
- create_iframe(rawName, event.data.launch.href)
12162
+ create_iframe(rawName, launchHref)
10896
12163
  }
10897
12164
  refresh()
10898
12165
  }
@@ -14507,14 +15774,15 @@ const rerenderMenuSection = (container, html) => {
14507
15774
  })
14508
15775
  }
14509
15776
 
14510
- const setChip = (name, visible, text) => {
14511
- roots.forEach((root) => {
14512
- const chip = root.querySelector(`[data-resource-chip="${name}"]`)
14513
- if (!chip) return
14514
- chip.textContent = text
14515
- chip.classList.toggle("hidden", !visible)
14516
- })
14517
- }
15777
+ const setChip = (name, visible, text) => {
15778
+ roots.forEach((root) => {
15779
+ const chip = root.querySelector(`[data-resource-chip="${name}"]`)
15780
+ if (!chip) return
15781
+ const alwaysVisible = root.getAttribute("data-resource-always-visible") === "true"
15782
+ chip.textContent = text
15783
+ chip.classList.toggle("hidden", !(visible || alwaysVisible))
15784
+ })
15785
+ }
14518
15786
 
14519
15787
  const updateFromUsage = (usage) => {
14520
15788
  if (!usage || !usage.ok) {
@@ -14531,9 +15799,10 @@ const rerenderMenuSection = (container, html) => {
14531
15799
  const cpu = metrics.cpu || {}
14532
15800
  const vram = metrics.vram || {}
14533
15801
 
14534
- setChip("ram", !!(ram.enabled && ram.available), `RAM ${ram.formatted || "--"}`)
14535
- setChip("cpu", !!(cpu.enabled && cpu.available && cpu.percent != null), `CPU ${cpu.percent}%`)
14536
- setChip("vram", !!(vram.enabled && vram.available), `VRAM ${vram.formatted || "--"}`)
15802
+ const cpuPercent = Number(cpu.percent)
15803
+ setChip("ram", !!(ram.enabled && ram.available), `RAM ${ram.formatted || "--"}`)
15804
+ setChip("cpu", !!(cpu.enabled && cpu.available && Number.isFinite(cpuPercent)), `CPU ${Number.isFinite(cpuPercent) ? `${cpuPercent}%` : "--"}`)
15805
+ setChip("vram", !!(vram.enabled && vram.available), `VRAM ${vram.formatted || "--"}`)
14537
15806
 
14538
15807
  if (!usage.running) {
14539
15808
  setStatus("No running app process")
@@ -15075,6 +16344,9 @@ document.addEventListener("DOMContentLoaded", () => {
15075
16344
  const setOpen = (next, opts = {}) => {
15076
16345
  open = !!next
15077
16346
  if (open) {
16347
+ if (window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
16348
+ window.PinokioCloseOtherMobilePanels("ask-ai")
16349
+ }
15078
16350
  const eventDrawer = window.PinokioEventDrawer
15079
16351
  if (eventDrawer && typeof eventDrawer.close === "function") {
15080
16352
  eventDrawer.close()
@@ -16306,6 +17578,9 @@ document.addEventListener("DOMContentLoaded", () => {
16306
17578
 
16307
17579
  const setOpen = (next, options = {}) => {
16308
17580
  open = !!next
17581
+ if (open && window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
17582
+ window.PinokioCloseOtherMobilePanels("logs")
17583
+ }
16309
17584
  if (appcanvas) {
16310
17585
  appcanvas.classList.toggle("logs-open", open)
16311
17586
  }
@@ -16534,6 +17809,9 @@ document.addEventListener("DOMContentLoaded", () => {
16534
17809
  return
16535
17810
  }
16536
17811
  communityMode = nextMode
17812
+ if (communityMode && window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
17813
+ window.PinokioCloseOtherMobilePanels("feed")
17814
+ }
16537
17815
  appcanvas.classList.toggle("community-mode", communityMode)
16538
17816
  if (communityMode) {
16539
17817
  setExpanded(false)
@@ -17120,6 +18398,15 @@ document.addEventListener("DOMContentLoaded", () => {
17120
18398
  setOpen(open, { persist: false })
17121
18399
  updateState()
17122
18400
  syncCommunityModeFromUrl()
18401
+ window.PinokioCommunityDrawer = {
18402
+ closeMobileMode: () => setCommunityMode(false),
18403
+ close: (opts = {}) => {
18404
+ setCommunityMode(false)
18405
+ setOpen(false, opts)
18406
+ },
18407
+ isMobileMode: () => communityMode,
18408
+ isOpen: () => open
18409
+ }
17123
18410
 
17124
18411
  if (resizer) {
17125
18412
  let isResizing = false