pinokiod 7.3.9 → 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 (52) 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 +52 -88
  15. package/server/public/install.js +20 -2
  16. package/server/public/layout.js +1 -1
  17. package/server/public/nav.js +3 -1
  18. package/server/public/style.css +1455 -521
  19. package/server/public/tab-link-popover.css +162 -18
  20. package/server/public/tab-link-popover.js +230 -21
  21. package/server/public/task-launcher.css +182 -91
  22. package/server/public/terminal-settings.js +227 -50
  23. package/server/public/universal-launcher.css +42 -33
  24. package/server/public/urldropdown.css +284 -0
  25. package/server/views/app.ejs +1718 -352
  26. package/server/views/autolaunch.ejs +4 -5
  27. package/server/views/checkpoints.ejs +223 -50
  28. package/server/views/connect/huggingface.ejs +406 -325
  29. package/server/views/connect.ejs +0 -1
  30. package/server/views/github.ejs +277 -324
  31. package/server/views/index.ejs +65 -8
  32. package/server/views/install.ejs +134 -65
  33. package/server/views/logs.ejs +9 -8
  34. package/server/views/net.ejs +341 -64
  35. package/server/views/network.ejs +85 -63
  36. package/server/views/partials/main_sidebar.ejs +249 -24
  37. package/server/views/plugins.ejs +141 -3
  38. package/server/views/settings.ejs +103 -7
  39. package/server/views/setup.ejs +0 -5
  40. package/server/views/skills.ejs +0 -1
  41. package/server/views/task_list.ejs +0 -1
  42. package/server/views/terminal.ejs +285 -60
  43. package/server/views/terminals.ejs +346 -6
  44. package/server/views/tools.ejs +828 -1691
  45. package/test/caddy-install.test.js +53 -0
  46. package/test/connect-setup.test.js +16 -0
  47. package/test/github-connection.test.js +1 -1
  48. package/test/huggingface-bin.test.js +4 -4
  49. package/test/huggingface-connect.test.js +73 -0
  50. package/test/main-sidebar.test.js +31 -0
  51. package/test/shell-run-template.test.js +5 -1
  52. package/test/uv-bin.test.js +29 -0
@@ -96,6 +96,48 @@ body.app-page header.navheader h1 > .flexible {
96
96
  flex: 0 0 0;
97
97
  min-width: 0;
98
98
  }
99
+ body.app-page header.navheader .nav-labeled-action {
100
+ width: auto;
101
+ min-width: 0;
102
+ height: 28px;
103
+ flex: 0 0 auto;
104
+ flex-direction: row;
105
+ align-items: center;
106
+ justify-content: center;
107
+ gap: 6px;
108
+ padding: 0 10px;
109
+ border-radius: 6px;
110
+ white-space: nowrap;
111
+ line-height: 1;
112
+ text-transform: none;
113
+ }
114
+ body.app-page header.navheader .nav-labeled-action i {
115
+ margin: 0;
116
+ padding: 0;
117
+ font-size: 13px;
118
+ line-height: 1;
119
+ }
120
+ body.app-page .ask-ai-brand-icon {
121
+ display: inline-flex;
122
+ width: 14px;
123
+ height: 14px;
124
+ flex: 0 0 14px;
125
+ background: currentColor;
126
+ -webkit-mask: url('/pinokio-mark.svg') center / contain no-repeat;
127
+ mask: url('/pinokio-mark.svg') center / contain no-repeat;
128
+ }
129
+ body.app-page header.navheader .nav-labeled-action .nav-action-label {
130
+ display: inline-block;
131
+ font-size: 12px;
132
+ line-height: 1;
133
+ font-weight: 500;
134
+ }
135
+ body.app-page header.navheader .nav-labeled-action.selected,
136
+ body.app-page header.navheader .nav-labeled-action:hover,
137
+ body.app-page header.navheader .nav-labeled-action:focus-visible {
138
+ background: var(--pinokio-sidebar-tab-active-bg);
139
+ color: var(--pinokio-sidebar-tab-active-color);
140
+ }
99
141
  .resource-usage {
100
142
  position: relative;
101
143
  flex: 0 0 auto;
@@ -537,6 +579,142 @@ main.browserview {
537
579
  min-height: 0;
538
580
  display: flex;
539
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); }
540
718
  }
541
719
  .community-drawer {
542
720
  display: none;
@@ -1333,6 +1511,15 @@ body.dark .ask-ai-drawer-empty {
1333
1511
  body.dark .ask-ai-drawer-empty-title {
1334
1512
  color: rgba(248, 250, 252, 0.95);
1335
1513
  }
1514
+ .ask-ai-drawer-empty-subtitle {
1515
+ font-size: 12px;
1516
+ line-height: 1.4;
1517
+ margin-top: -6px;
1518
+ color: rgba(75, 85, 99, 0.78);
1519
+ }
1520
+ body.dark .ask-ai-drawer-empty-subtitle {
1521
+ color: rgba(209, 213, 219, 0.68);
1522
+ }
1336
1523
  .ask-ai-drawer-search {
1337
1524
  display: flex;
1338
1525
  align-items: center;
@@ -1802,9 +1989,15 @@ body.dark .appcanvas_filler {
1802
1989
  }
1803
1990
  .appcanvas.vertical .appcanvas-resizer {
1804
1991
  display: flex;
1805
- flex: 0 0 0px;
1992
+ flex: 0 0 8px;
1993
+ width: 8px;
1994
+ min-width: 8px;
1995
+ margin-left: -4px;
1996
+ margin-right: -4px;
1806
1997
  align-items: stretch;
1807
1998
  justify-content: center;
1999
+ position: relative;
2000
+ z-index: 3;
1808
2001
  cursor: col-resize;
1809
2002
  touch-action: none;
1810
2003
  outline: none;
@@ -5054,7 +5247,7 @@ body.dark .pinokio-git-diff-viewer-header {
5054
5247
  .pinokio-modal-tabs {
5055
5248
  display: inline-flex;
5056
5249
  gap: 8px;
5057
- padding: 0 6px;
5250
+ padding: 0 14px;
5058
5251
  }
5059
5252
 
5060
5253
  .pinokio-modal-tab {
@@ -6136,11 +6329,14 @@ body.dark .snapshot-footer-input input {
6136
6329
  .snapshot-footer-input input::placeholder {
6137
6330
  opacity: 0.7;
6138
6331
  }
6139
- .mobile-bottom-nav,
6140
- .mobile-sheet-actions,
6141
- .mobile-menu-fallback {
6142
- display: none;
6143
- }
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
+ }
6144
6340
  header.navheader h1 {
6145
6341
  position: relative;
6146
6342
  }
@@ -6159,10 +6355,10 @@ header.navheader h1 {
6159
6355
  margin: 0 10px;
6160
6356
  }
6161
6357
  }
6162
- @media only screen and (max-width: 768px) {
6163
- :root {
6164
- --mobile-bottom-bar-height: calc(33px + env(safe-area-inset-bottom));
6165
- }
6358
+ @media only screen and (max-width: 768px) {
6359
+ :root {
6360
+ --mobile-bottom-bar-height: calc(46px + env(safe-area-inset-bottom));
6361
+ }
6166
6362
  .appcanvas.vertical {
6167
6363
  flex-direction: column;
6168
6364
  }
@@ -6188,85 +6384,92 @@ header.navheader h1 {
6188
6384
  header.navheader .app-header-identity {
6189
6385
  display: none !important;
6190
6386
  }
6191
- body:not(.mobile-menu-open) .appcanvas > aside {
6192
- display: none;
6193
- }
6194
- body.mobile-menu-open #menu-mobile-close {
6195
- display: inline-flex;
6196
- }
6197
- .browserview-shell {
6198
- box-sizing: border-box;
6199
- }
6200
- .mobile-bottom-nav {
6201
- position: sticky;
6202
- bottom: 0;
6203
- display: flex;
6204
- flex: 0 0 auto;
6205
- align-items: center;
6206
- gap: 3px;
6207
- width: 100%;
6208
- margin-top: auto;
6209
- min-height: 32px;
6210
- padding: 0 4px env(safe-area-inset-bottom) 4px;
6211
- border-top: 1px solid rgba(0,0,0,0.08);
6212
- background: rgba(255,255,255,0.96);
6213
- backdrop-filter: blur(20px);
6214
- z-index: 10000002;
6215
- box-sizing: border-box;
6216
- }
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
+ }
6217
6407
  body.dark .mobile-bottom-nav {
6218
6408
  background: rgba(15, 17, 21, 0.96);
6219
6409
  border-top-color: rgba(255,255,255,0.08);
6220
6410
  }
6221
- .mobile-bottom-nav__button {
6222
- flex: 0 0 28px;
6223
- min-width: 28px;
6224
- max-width: 28px;
6225
- min-height: 28px;
6226
- display: flex;
6227
- align-items: center;
6228
- justify-content: center;
6229
- gap: 0;
6230
- padding: 0;
6231
- border-radius: 7px;
6232
- background: transparent;
6233
- color: #64748b;
6234
- text-decoration: none;
6235
- }
6236
- .mobile-bottom-nav__button i {
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;
6427
+ }
6428
+ .mobile-bottom-nav__button i,
6429
+ .mobile-bottom-nav__button .ask-ai-brand-icon {
6237
6430
  font-size: 14px;
6238
6431
  }
6239
- .mobile-bottom-nav__button.selected {
6240
- background: rgba(10, 132, 255, 0.12);
6241
- color: #0a84ff;
6242
- }
6243
- body.dark .mobile-bottom-nav__button {
6244
- color: rgba(148, 163, 184, 0.9);
6245
- }
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
+ }
6246
6446
  body.dark .mobile-bottom-nav__button.selected {
6247
6447
  background: rgba(10, 132, 255, 0.18);
6248
6448
  color: #63a9ff;
6249
6449
  }
6250
- .mobile-bottom-nav__logo {
6251
- width: 25px;
6252
- height: 25px;
6253
- object-fit: contain;
6254
- display: block;
6255
- }
6256
- .mobile-bottom-nav__identity {
6257
- flex: 1 1 auto;
6258
- min-width: 0;
6259
- display: flex;
6260
- align-items: center;
6261
- justify-content: center;
6262
- gap: 6px;
6263
- height: 28px;
6264
- padding: 0 10px;
6265
- border-radius: 999px;
6266
- border: 1px solid rgba(0,0,0,0.08);
6267
- background: rgba(255, 255, 255, 0.78);
6268
- box-sizing: border-box;
6269
- }
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
+ }
6270
6473
  body.dark .mobile-bottom-nav__identity {
6271
6474
  border-color: rgba(255,255,255,0.08);
6272
6475
  background: rgba(255,255,255,0.06);
@@ -6278,16 +6481,17 @@ header.navheader h1 {
6278
6481
  object-fit: contain;
6279
6482
  display: block;
6280
6483
  }
6281
- .mobile-bottom-nav__identity-title {
6282
- min-width: 0;
6283
- overflow: hidden;
6284
- text-overflow: ellipsis;
6285
- white-space: nowrap;
6286
- color: #0f172a;
6287
- font-size: 12px;
6288
- font-weight: 700;
6289
- line-height: 1;
6290
- }
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
+ }
6291
6495
  body.dark .mobile-bottom-nav__identity-title {
6292
6496
  color: rgba(248, 250, 252, 0.94);
6293
6497
  }
@@ -6301,22 +6505,19 @@ header.navheader h1 {
6301
6505
  body.dark .mobile-bottom-nav__identity-separator {
6302
6506
  background: rgba(148, 163, 184, 0.6);
6303
6507
  }
6304
- .mobile-bottom-nav__identity-disk {
6305
- flex: 0 0 auto;
6306
- display: inline-flex;
6307
- align-items: center;
6308
- min-width: 0;
6309
- max-width: 78px;
6310
- overflow: hidden;
6311
- text-overflow: ellipsis;
6312
- padding: 0;
6313
- border: 0 !important;
6314
- border-radius: 0;
6315
- color: rgba(71, 85, 105, 0.74);
6316
- font-size: 10px;
6317
- font-weight: 600;
6318
- line-height: 1;
6319
- 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;
6320
6521
  cursor: default;
6321
6522
  }
6322
6523
  body.dark .mobile-bottom-nav__identity-disk {
@@ -6325,60 +6526,134 @@ header.navheader h1 {
6325
6526
  .mobile-bottom-nav__identity-disk i {
6326
6527
  display: none;
6327
6528
  }
6328
- .mobile-bottom-nav .resource-usage {
6329
- max-width: min(46vw, 190px);
6330
- }
6331
- .mobile-bottom-nav .resource-usage-trigger {
6332
- gap: 5px;
6333
- overflow: hidden;
6334
- }
6335
- .mobile-bottom-nav .resource-chip {
6336
- max-width: 82px;
6337
- overflow: hidden;
6338
- text-overflow: ellipsis;
6339
- font-size: 10px;
6340
- }
6341
- .mobile-bottom-nav .resource-chip--cpu,
6342
- .mobile-bottom-nav .resource-chip--ram,
6343
- .mobile-bottom-nav .resource-chip--vram {
6344
- display: none !important;
6345
- }
6346
- .mobile-bottom-nav .resource-usage-popover {
6347
- top: auto;
6348
- bottom: calc(100% + 9px);
6349
- right: -4px;
6350
- }
6351
- body.mobile-menu-open .appcanvas > aside {
6352
- display: flex;
6353
- position: fixed;
6354
- inset: 0;
6355
- bottom: var(--mobile-bottom-bar-height);
6356
- width: 100%;
6357
- max-width: none;
6358
- border-left: 0;
6359
- z-index: 10000001;
6360
- background: #f2f2f7;
6361
- }
6362
- body.mobile-menu-open .appcanvas.sidebar-collapsed > aside {
6363
- width: 100%;
6364
- min-width: 0;
6365
- max-width: none;
6366
- opacity: 1;
6367
- pointer-events: auto;
6368
- }
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
+ }
6369
6633
  body.mobile-menu-open .appcanvas.sidebar-collapsed > aside .menu-container {
6370
6634
  width: 100%;
6371
6635
  }
6372
- body.dark.mobile-menu-open .appcanvas > aside {
6373
- background: #0f1115;
6374
- }
6375
- body.mobile-menu-open .appcanvas > aside .menu-container {
6376
- width: 100%;
6377
- flex-direction: column;
6378
- align-items: stretch;
6379
- gap: 8px;
6380
- padding-top: 0;
6381
- }
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
+ }
6382
6657
  body.mobile-menu-open .appcanvas > aside .config-info {
6383
6658
  padding: 6px 8px 2px;
6384
6659
  font-size: 15px;
@@ -6393,16 +6668,16 @@ header.navheader h1 {
6393
6668
  body.dark.mobile-menu-open .appcanvas > aside .disk-usage {
6394
6669
  color: rgba(148, 163, 184, 0.9);
6395
6670
  }
6396
- body.mobile-menu-open .appcanvas > aside .menu-scroller {
6397
- flex-direction: column;
6398
- align-items: stretch;
6399
- overflow-y: auto;
6400
- overflow-x: hidden;
6401
- width: 100%;
6402
- padding: 12px 12px 14px;
6403
- gap: 12px;
6404
- box-sizing: border-box;
6405
- }
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
+ }
6406
6681
  body.mobile-menu-open .appcanvas > aside .workspace-mode-switch,
6407
6682
  body.mobile-menu-open .mobile-menu-fallback .workspace-mode-switch {
6408
6683
  flex-direction: row;
@@ -6430,14 +6705,14 @@ header.navheader h1 {
6430
6705
  display: flex;
6431
6706
  flex-direction: column;
6432
6707
  align-items: stretch;
6433
- gap: 8px;
6708
+ gap: 4px;
6434
6709
  width: 100%;
6435
6710
  }
6436
- body.mobile-menu-open .appcanvas > aside .mobile-sheet-actions {
6437
- display: flex;
6438
- align-items: center;
6439
- gap: 8px;
6440
- 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%;
6441
6716
  overflow-x: auto;
6442
6717
  overflow-y: hidden;
6443
6718
  padding-bottom: 2px;
@@ -6494,11 +6769,11 @@ header.navheader h1 {
6494
6769
  justify-content: center;
6495
6770
  gap: 0;
6496
6771
  }
6497
- body.mobile-menu-open[data-view='files'] .mobile-menu-fallback .mobile-sheet-actions {
6498
- display: flex;
6499
- align-items: center;
6500
- gap: 8px;
6501
- 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%;
6502
6777
  overflow-x: auto;
6503
6778
  overflow-y: hidden;
6504
6779
  padding-bottom: 2px;
@@ -6508,56 +6783,195 @@ header.navheader h1 {
6508
6783
  max-width: none;
6509
6784
  min-width: 0;
6510
6785
  width: 100%;
6511
- padding: 12px 14px;
6512
- border-radius: 14px;
6513
- border: 1px solid rgba(0,0,0,0.06);
6514
- background: #fff;
6515
- color: #111827;
6516
- 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;
6517
6793
  box-sizing: border-box;
6518
- min-height: 44px;
6519
6794
  }
6520
6795
  body.dark.mobile-menu-open .appcanvas > aside .menu-scroller .btn:not(.btn2),
6521
6796
  body.dark.mobile-menu-open .appcanvas > aside .menu-actions .btn:not(.btn2) {
6522
- background: rgba(15, 17, 21, 0.8);
6523
- border-color: rgba(255,255,255,0.08);
6524
- color: rgba(226, 232, 240, 0.9);
6525
- 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);
6526
6813
  }
6527
6814
  body.mobile-menu-open .appcanvas > aside .menu-scroller .tab,
6528
6815
  body.mobile-menu-open .appcanvas > aside .menu-actions .tab {
6529
- gap: 12px;
6816
+ gap: 10px;
6817
+ font-size: 12px;
6818
+ line-height: 1.25;
6819
+ font-weight: 500;
6530
6820
  }
6531
6821
  body.mobile-menu-open .appcanvas > aside .menu-scroller .display,
6532
6822
  body.mobile-menu-open .appcanvas > aside .menu-actions .display {
6533
- 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;
6534
6832
  }
6535
6833
  body.mobile-menu-open .appcanvas > aside .menu-scroller .tab i,
6536
6834
  body.mobile-menu-open .appcanvas > aside .menu-actions .tab i {
6537
- font-size: 15px;
6835
+ color: var(--app-mobile-drawer-icon-muted) !important;
6836
+ font-size: 14px !important;
6837
+ opacity: 1;
6538
6838
  }
6539
- body.mobile-menu-open .appcanvas > aside .menu-actions {
6540
- 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;
6541
6846
  }
6542
- .mobile-menu-fallback {
6847
+ body.mobile-menu-open .appcanvas > aside .menu-actions {
6543
6848
  display: none;
6544
6849
  }
6545
- 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 {
6546
6852
  display: flex;
6547
- position: fixed;
6548
- inset: 0;
6549
- bottom: var(--mobile-bottom-bar-height);
6550
- z-index: 10000001;
6551
6853
  flex-direction: column;
6552
- 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);
6553
6860
  }
6554
- body.dark.mobile-menu-open[data-view='files'] .mobile-menu-fallback {
6555
- background: #0f1115;
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;
6556
6877
  }
6557
- .mobile-menu-fallback__header {
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);
6884
+ }
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 {
6558
6892
  display: flex;
6559
6893
  align-items: center;
6560
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;
6561
6975
  padding: 12px;
6562
6976
  font-size: 15px;
6563
6977
  font-weight: 700;
@@ -6568,12 +6982,12 @@ header.navheader h1 {
6568
6982
  object-fit: contain;
6569
6983
  display: block;
6570
6984
  }
6571
- .mobile-menu-fallback__body {
6572
- flex: 1 1 auto;
6573
- overflow-y: auto;
6574
- padding: 0 12px 16px;
6575
- box-sizing: border-box;
6576
- }
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
+ }
6577
6991
  .mobile-menu-fallback .workspace-mode-switch {
6578
6992
  display: flex;
6579
6993
  align-items: center;
@@ -6589,12 +7003,9 @@ header.navheader h1 {
6589
7003
  border-color: rgba(255, 255, 255, 0.075);
6590
7004
  background: rgba(255, 255, 255, 0.045);
6591
7005
  }
6592
- body.mobile-menu-open .appcanvas .container {
6593
- display: none;
6594
- }
6595
- #community-toggle {
6596
- display: none;
6597
- }
7006
+ #community-toggle {
7007
+ display: none;
7008
+ }
6598
7009
  .appcanvas.panel-open .ask-ai-drawer,
6599
7010
  .appcanvas.logs-open .app-logs-drawer,
6600
7011
  .appcanvas.event-drawer-open .event-launch-drawer,
@@ -6634,11 +7045,533 @@ header.navheader h1 {
6634
7045
  .appcanvas.community-mode .community-resizer {
6635
7046
  display: none;
6636
7047
  }
6637
- .appcanvas.community-mode main.browserview {
6638
- 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;
6639
7571
  }
6640
- .appcanvas.community-mode .browserview-shell {
6641
- flex: 1 1 auto;
7572
+
7573
+ .pinokio-github-login {
7574
+ padding: 20px 16px 16px !important;
6642
7575
  }
6643
7576
  }
6644
7577
  </style>
@@ -6703,8 +7636,10 @@ header.navheader h1 {
6703
7636
  <button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
6704
7637
  <button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
6705
7638
  <button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
7639
+ <!-- Screen capture and X-ray mode are hidden for now.
6706
7640
  <button class='btn2' id='screenshot' data-tippy-content="screen capture"><i class="fa-solid fa-camera"></i></button>
6707
7641
  <button class='btn2' id='inspector' data-tippy-content="X-ray mode"><i class="fa-solid fa-eye"></i></button>
7642
+ -->
6708
7643
  <button class='btn2' id='menu-mobile' data-tippy-content="Tabs">
6709
7644
  <div><i class="fa-solid fa-list"></i></div>
6710
7645
  </button>
@@ -6748,6 +7683,36 @@ header.navheader h1 {
6748
7683
  </button>
6749
7684
  <% } %>
6750
7685
  <div class='flexible'></div>
7686
+ <% if (type === 'run') { %>
7687
+ <button
7688
+ type='button'
7689
+ id='ask-ai-tab'
7690
+ class="btn2 nav-labeled-action"
7691
+ data-static="ask-ai"
7692
+ data-workspace="<%=name%>"
7693
+ data-workspace-cwd="<%=path%>"
7694
+ data-ask-ai-trigger="true"
7695
+ data-tippy-content="Ask AI"
7696
+ aria-label="Ask AI"
7697
+ aria-expanded="false"
7698
+ aria-controls="ask-ai-drawer">
7699
+ <span class="ask-ai-brand-icon" aria-hidden="true"></span>
7700
+ <span class="nav-action-label">Ask AI</span>
7701
+ </button>
7702
+ <% } %>
7703
+ <% if (registryEnabled) { %>
7704
+ <button
7705
+ type='button'
7706
+ id='community-toggle'
7707
+ class="btn2 nav-labeled-action"
7708
+ data-tippy-content="Project feed"
7709
+ aria-label="Project feed"
7710
+ aria-expanded="false"
7711
+ aria-controls="community-drawer">
7712
+ <i class="fa-solid fa-rss" aria-hidden="true"></i>
7713
+ <span class="nav-action-label">Feed</span>
7714
+ </button>
7715
+ <% } %>
6751
7716
  <a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
6752
7717
  <div><i class="fa-solid fa-table-columns"></i></div>
6753
7718
  </a>
@@ -6781,9 +7746,6 @@ header.navheader h1 {
6781
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">
6782
7747
  <i class="fa-solid fa-xmark"></i>
6783
7748
  </button>
6784
- <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
6785
- <i class="fa-solid fa-house"></i>
6786
- </a>
6787
7749
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
6788
7750
  <i class="fa-solid fa-rotate-right"></i>
6789
7751
  </button>
@@ -6828,8 +7790,8 @@ header.navheader h1 {
6828
7790
  </div>
6829
7791
  </div>
6830
7792
  <% } %>
6831
- <%if (type === 'run') { %>
6832
- <div class='m h menu' data-type='h'>
7793
+ <%if (type === 'run') { %>
7794
+ <div class='m h menu' data-type='h'>
6833
7795
  <% if (config.menu) { %>
6834
7796
  <%- include('./partials/menu', { menu: config.menu, }) %>
6835
7797
  <% } %>
@@ -6840,9 +7802,9 @@ header.navheader h1 {
6840
7802
  <div class='flexible'></div>
6841
7803
  </div>
6842
7804
  </a>
6843
- </div>
6844
- <% } %>
6845
- <div class='m s temp-menu' data-type='s'>
7805
+ </div>
7806
+ <% } %>
7807
+ <div class='m s temp-menu' data-type='s'>
6846
7808
  <%tabs.forEach((tab, i) => { %>
6847
7809
  <% const tabHref = typeof tab === "string" ? tab : ((tab && typeof tab.href === "string") ? tab.href : "") %>
6848
7810
  <% const tabLabel = typeof tab === "string" ? tab : ((tab && typeof tab.label === "string" && tab.label.trim().length > 0) ? tab.label.trim() : tabHref) %>
@@ -6853,22 +7815,47 @@ header.navheader h1 {
6853
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><% } %>
6854
7816
  </div>
6855
7817
  </a>
6856
- <%})%>
6857
- </div>
6858
- </div>
6859
- <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" : "" %>'>
6860
7856
  <% if (type === 'browse') { %>
6861
7857
  <%- include('./partials/fs_status') %>
6862
7858
  <% } %>
6863
- <% if (type === 'run') { %>
6864
- <button type='button' id='ask-ai-tab' class="btn header-item" data-static="ask-ai" data-workspace="<%=name%>" data-workspace-cwd="<%=path%>" data-ask-ai-trigger="true" data-tippy-content="Ask AI">
6865
- <div class='tab'>
6866
- <span class="menu-action-leading-icon ask-ai-brand-icon" aria-hidden="true"></span>
6867
- <div class='display'>Ask AI</div>
6868
- <div class='flexible'></div>
6869
- </div>
6870
- </button>
6871
- <% } %>
6872
7859
  <button type='button' id='logs-toggle' class="btn header-item" data-tippy-content="logs" aria-expanded="false" aria-controls="app-logs-drawer">
6873
7860
  <div class='tab'>
6874
7861
  <i class="fa-solid fa-laptop-code menu-action-leading-icon"></i>
@@ -6877,15 +7864,6 @@ header.navheader h1 {
6877
7864
  <span class='logs-new-badge hidden' id='logs-new-badge'>New</span>
6878
7865
  </div>
6879
7866
  </button>
6880
- <% if (registryEnabled) { %>
6881
- <button type='button' id='community-toggle' class="btn header-item" data-tippy-content="community">
6882
- <div class='tab'>
6883
- <i class="fa-solid fa-globe menu-action-leading-icon"></i>
6884
- <div class='display'>Community</div>
6885
- <div class='flexible'></div>
6886
- </div>
6887
- </button>
6888
- <% } %>
6889
7867
  <button type='button' id='sidebar-open-explorer' class="btn header-item" data-filepath="<%=path%>" data-tippy-content="Open in File Explorer">
6890
7868
  <div class='tab'>
6891
7869
  <i class="fa-solid fa-folder-open menu-action-leading-icon"></i>
@@ -6896,20 +7874,20 @@ header.navheader h1 {
6896
7874
  <% if (typeof autolaunch_app !== 'undefined' && autolaunch_app) { %>
6897
7875
  <div class="app-autolaunch" data-app-autolaunch data-app-id="<%=name%>">
6898
7876
  <button type="button" class="app-autolaunch-row" data-app-autolaunch-button data-enabled="<%= autolaunch_app.autolaunch_enabled ? 'true' : 'false' %>" aria-haspopup="dialog" aria-expanded="false">
6899
- <span class="app-autolaunch-label"><i class="fa-solid fa-power-off"></i><span>Auto</span></span>
7877
+ <span class="app-autolaunch-label"><i class="fa-solid fa-power-off"></i><span>Autolaunch</span></span>
6900
7878
  <span class="app-autolaunch-spacer" aria-hidden="true"></span>
6901
7879
  <span class="app-autolaunch-status" data-app-autolaunch-status><%= autolaunch_app.autolaunch_enabled ? 'ON' : 'OFF' %></span>
6902
7880
  <i class="fa-solid fa-angle-down app-autolaunch-chevron" aria-hidden="true"></i>
6903
7881
  </button>
6904
- <div class="app-autolaunch-modal hidden" data-app-autolaunch-modal role="dialog" aria-modal="true" aria-label="Auto launch">
7882
+ <div class="app-autolaunch-modal hidden" data-app-autolaunch-modal role="dialog" aria-modal="true" aria-label="Autolaunch">
6905
7883
  <div class="app-autolaunch-panel" data-app-autolaunch-panel>
6906
7884
  <div class="app-autolaunch-modal-head">
6907
7885
  <div>
6908
- <div class="app-autolaunch-title">Auto launch</div>
7886
+ <div class="app-autolaunch-title">Autolaunch</div>
6909
7887
  <div class="app-autolaunch-note">Run this app when Pinokio starts.</div>
6910
7888
  </div>
6911
7889
  <div class="app-autolaunch-modal-actions">
6912
- <button type="button" class="app-autolaunch-switch" role="switch" aria-checked="<%= autolaunch_app.autolaunch_enabled ? 'true' : 'false' %>" data-app-autolaunch-switch aria-label="Auto launch" title="Auto launch is <%= autolaunch_app.autolaunch_enabled ? 'on' : 'off' %>">
7890
+ <button type="button" class="app-autolaunch-switch" role="switch" aria-checked="<%= autolaunch_app.autolaunch_enabled ? 'true' : 'false' %>" data-app-autolaunch-switch aria-label="Autolaunch" title="Autolaunch is <%= autolaunch_app.autolaunch_enabled ? 'on' : 'off' %>">
6913
7891
  <span class="app-autolaunch-switch-label" data-app-autolaunch-switch-label><%= autolaunch_app.autolaunch_enabled ? 'ON' : 'OFF' %></span>
6914
7892
  <span class="app-autolaunch-switch-thumb" aria-hidden="true"></span>
6915
7893
  </button>
@@ -7004,6 +7982,7 @@ header.navheader h1 {
7004
7982
  <% if (type === 'files') { %>
7005
7983
  <iframe class='selected' src="<%=editor_tab%>" allow="fullscreen *;" allowfullscreen></iframe>
7006
7984
  <% } %>
7985
+ <div id="browserview-network-status" class="browserview-network-status" hidden aria-live="polite"></div>
7007
7986
  <%- include('./partials/browser_popout_surface') %>
7008
7987
  </main>
7009
7988
  <% if (type === 'run') { %>
@@ -7012,7 +7991,7 @@ header.navheader h1 {
7012
7991
  <div class='ask-ai-drawer-inner'>
7013
7992
  <div class='ask-ai-drawer-bar'>
7014
7993
  <div class='ask-ai-drawer-title'>
7015
- <i class="fa-solid fa-robot" aria-hidden="true"></i>
7994
+ <span class="ask-ai-brand-icon" aria-hidden="true"></span>
7016
7995
  <span>Ask AI</span>
7017
7996
  </div>
7018
7997
  <div class='ask-ai-drawer-actions'>
@@ -7034,11 +8013,12 @@ header.navheader h1 {
7034
8013
  <div class='ask-ai-drawer-empty'>
7035
8014
  <div class='ask-ai-drawer-search'>
7036
8015
  <i class="fa-solid fa-magnifying-glass" aria-hidden="true"></i>
7037
- <input class='ask-ai-drawer-search-input' type='search' placeholder="Filter tools" autocomplete="off" spellcheck="false" aria-label="Filter Ask AI launch options">
8016
+ <input class='ask-ai-drawer-search-input' type='search' placeholder="Search shells and plugins" autocomplete="off" spellcheck="false" aria-label="Search shells and plugins">
7038
8017
  </div>
7039
- <div class='ask-ai-drawer-empty-title'>Pick a shell or plugin to launch</div>
7040
- <div class='ask-ai-drawer-picker-list' role="list" aria-label="Ask AI launch options"></div>
7041
- <div class='ask-ai-drawer-picker-status muted'>Use the Ask AI button to load launch options.</div>
8018
+ <div class='ask-ai-drawer-empty-title'>Ask an AI agent about this project</div>
8019
+ <div class='ask-ai-drawer-empty-subtitle'>Choose the shell or plugin the agent should use.</div>
8020
+ <div class='ask-ai-drawer-picker-list' role="list" aria-label="Ask AI shells and plugins"></div>
8021
+ <div class='ask-ai-drawer-picker-status muted'>Choose a shell or plugin to start an agent.</div>
7042
8022
  </div>
7043
8023
  <iframe class='ask-ai-frame hidden' title="Panel" allow="fullscreen *;" allowfullscreen></iframe>
7044
8024
  </div>
@@ -7122,9 +8102,9 @@ header.navheader h1 {
7122
8102
  <div class='community-drawer-inner'>
7123
8103
  <div class='community-drawer-bar'>
7124
8104
  <div class='community-drawer-title'>
7125
- <button type="button" class="community-drawer-home" data-tippy-content="Community home" aria-label="Community home">
7126
- <i class="fa-solid fa-globe"></i>
7127
- <span>Community</span>
8105
+ <button type="button" class="community-drawer-home" data-tippy-content="Project feed" aria-label="Project feed">
8106
+ <i class="fa-solid fa-rss"></i>
8107
+ <span>Feed</span>
7128
8108
  </button>
7129
8109
  <span class='community-drawer-status' data-state="offline" data-tippy-content="Offline" aria-label="Offline" role="img"></span>
7130
8110
  </div>
@@ -7135,7 +8115,7 @@ header.navheader h1 {
7135
8115
  <button type='button' class='btn2 community-drawer-forward' disabled data-tippy-content="Forward" aria-label="Forward">
7136
8116
  <i class="fa-solid fa-chevron-right"></i>
7137
8117
  </button>
7138
- <button type='button' class='btn2 community-drawer-refresh' disabled data-tippy-content="Refresh" aria-label="Refresh community">
8118
+ <button type='button' class='btn2 community-drawer-refresh' disabled data-tippy-content="Refresh" aria-label="Refresh feed">
7139
8119
  <i class="fa-solid fa-rotate-right"></i>
7140
8120
  </button>
7141
8121
  <button type='button' class='btn2 community-drawer-toggle' data-tippy-content="Connect to Pinokio Network" aria-label="Connect to Pinokio Network">
@@ -7144,15 +8124,15 @@ header.navheader h1 {
7144
8124
  <button type='button' class='btn2 community-drawer-expand' data-tippy-content="Expand panel" aria-label="Expand panel" aria-pressed="false">
7145
8125
  <i class="fa-solid fa-expand"></i>
7146
8126
  </button>
7147
- <button type='button' class='btn2 community-drawer-close' data-tippy-content="Close panel" aria-label="Close community panel">
8127
+ <button type='button' class='btn2 community-drawer-close' data-tippy-content="Close panel" aria-label="Close feed panel">
7148
8128
  <i class="fa-solid fa-xmark"></i>
7149
8129
  </button>
7150
8130
  </div>
7151
8131
  </div>
7152
8132
  <div class='community-drawer-location'>
7153
- <input class='community-drawer-location-input' type='text' value="" readonly aria-label="Community URL">
8133
+ <input class='community-drawer-location-input' type='text' value="" readonly aria-label="Feed URL">
7154
8134
  <div class='community-drawer-location-overlay' aria-hidden="true"></div>
7155
- <textarea class='community-drawer-location-textarea' rows="1" readonly aria-label="Community URL"></textarea>
8135
+ <textarea class='community-drawer-location-textarea' rows="1" readonly aria-label="Feed URL"></textarea>
7156
8136
  </div>
7157
8137
  <div class='community-drawer-body'>
7158
8138
  <div class='community-drawer-empty'>
@@ -7160,12 +8140,12 @@ header.navheader h1 {
7160
8140
  <div class='community-drawer-empty-icon'>
7161
8141
  <i class="fa-solid fa-plug-circle-xmark" aria-hidden="true"></i>
7162
8142
  </div>
7163
- <div class='community-drawer-empty-title'>Load Community</div>
8143
+ <div class='community-drawer-empty-title'>Load Feed</div>
7164
8144
  </div>
7165
8145
  <div class='community-drawer-empty-note muted'>Load https://pinokio.co in the panel (requires network)</div>
7166
8146
  <button type='button' class='btn community-drawer-connect'>Load</button>
7167
8147
  </div>
7168
- <iframe class='community-frame hidden' title="Community updates" allow="fullscreen *;" allowfullscreen></iframe>
8148
+ <iframe class='community-frame hidden' title="Project feed" allow="fullscreen *;" allowfullscreen></iframe>
7169
8149
  </div>
7170
8150
  </div>
7171
8151
  </aside>
@@ -7189,6 +8169,7 @@ header.navheader h1 {
7189
8169
  </div>
7190
8170
  <% } %>
7191
8171
  </div>
8172
+ <button type='button' class='mobile-menu-backdrop' data-mobile-menu-backdrop aria-label="Close Pinokio menu" hidden></button>
7192
8173
  <nav class='mobile-bottom-nav' aria-label="Mobile navigation">
7193
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">
7194
8175
  <img class='mobile-bottom-nav__logo' src="/pinokio-black.png" alt="" aria-hidden="true">
@@ -7199,14 +8180,14 @@ header.navheader h1 {
7199
8180
  <% } %>
7200
8181
  <span class='mobile-bottom-nav__identity-title'><%=config.title || name%></span>
7201
8182
  <span class='mobile-bottom-nav__identity-separator' aria-hidden="true"></span>
7202
- <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%>">
7203
8184
  <button type="button" class="resource-usage-trigger" data-resource-usage-trigger aria-haspopup="dialog" aria-expanded="false" aria-label="Resource usage">
7204
8185
  <span class="resource-chip resource-chip--disk">
7205
8186
  <span class="disk-usage mobile-bottom-nav__identity-disk" data-path="/" data-filepath="<%=path%>" data-metric-label="Disk">--</span>
7206
8187
  </span>
7207
- <span class="resource-chip resource-chip--cpu hidden" data-resource-chip="cpu">CPU --</span>
7208
- <span class="resource-chip resource-chip--ram hidden" data-resource-chip="ram">RAM --</span>
7209
- <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>
7210
8191
  </button>
7211
8192
  <div class="resource-usage-popover hidden" data-resource-usage-popover role="dialog" aria-label="Resource usage settings">
7212
8193
  <div class="resource-usage-popover-head">Resources</div>
@@ -7226,19 +8207,6 @@ header.navheader h1 {
7226
8207
  </div>
7227
8208
  </div>
7228
8209
  </div>
7229
- <% if (registryEnabled) { %>
7230
- <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="Community">
7231
- <i class="fa-solid fa-globe"></i>
7232
- </button>
7233
- <% } %>
7234
- <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">
7235
- <i class="fa-solid fa-laptop-code"></i>
7236
- </button>
7237
- <% if (type === 'run') { %>
7238
- <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">
7239
- <i class="fa-solid fa-robot"></i>
7240
- </button>
7241
- <% } %>
7242
8210
  </nav>
7243
8211
  </div>
7244
8212
  <div class='mobile-menu-fallback' aria-hidden="true">
@@ -7261,9 +8229,6 @@ header.navheader h1 {
7261
8229
  </a>
7262
8230
  </div>
7263
8231
  <div class='mobile-sheet-actions' aria-label="Workspace actions">
7264
- <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
7265
- <i class="fa-solid fa-house"></i>
7266
- </a>
7267
8232
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
7268
8233
  <i class="fa-solid fa-rotate-right"></i>
7269
8234
  </button>
@@ -7286,6 +8251,31 @@ header.navheader h1 {
7286
8251
  <i class="fa-solid fa-xmark"></i>
7287
8252
  </button>
7288
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>
7289
8279
  </div>
7290
8280
  </div>
7291
8281
  <script>
@@ -7352,6 +8342,95 @@ header.navheader h1 {
7352
8342
  let initialHomeSelectionRetries = 0
7353
8343
  let ignorePersistedSelection = pluginLaunchActive || Boolean(initialHomeSelectionPayload)
7354
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
+ }
7355
8434
  const browserPopoutSurface = window.createBrowserPopoutSurface({
7356
8435
  onShow: () => {
7357
8436
  lastForegroundSignature = null
@@ -7493,6 +8572,10 @@ header.navheader h1 {
7493
8572
  frame.setAttribute("data-pinokio-inject", serialized)
7494
8573
  }
7495
8574
  const create_iframe = (name, href, injectDescriptors = []) => {
8575
+ if (showNetworkSharingRequired(href)) {
8576
+ return
8577
+ }
8578
+ clearBrowserviewNetworkStatus()
7496
8579
  document.querySelectorAll(".menu-container .selected").forEach((el) => {
7497
8580
  el.classList.remove("selected")
7498
8581
  })
@@ -7578,6 +8661,113 @@ header.navheader h1 {
7578
8661
  }
7579
8662
  })
7580
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
+ }
7581
8771
  const previewClass = "tab-preview"
7582
8772
  const tabMainClass = "tab-main"
7583
8773
  const tabDetailsClass = "tab-details"
@@ -8956,6 +10146,7 @@ const rerenderMenuSection = (container, html) => {
8956
10146
  }
8957
10147
 
8958
10148
  if (!target) {
10149
+ clearBrowserviewNetworkStatus()
8959
10150
  syncActiveNestedPath()
8960
10151
  if (typeof syncLogsSelectedState === "function") {
8961
10152
  syncLogsSelectedState(null)
@@ -8966,15 +10157,92 @@ const rerenderMenuSection = (container, html) => {
8966
10157
  return
8967
10158
  }
8968
10159
 
8969
- document.querySelector(".container").classList.add("active")
8970
- document.querySelector("aside").classList.remove("active")
10160
+ document.querySelector(".container").classList.add("active")
10161
+ document.querySelector("aside").classList.remove("active")
8971
10162
 
8972
10163
 
8973
- // Instantiate a frame with the selected target's href
8974
- const targetInjectDescriptors = readLinkInjectDescriptors(target)
8975
- if (!target.href) {
8976
- return
8977
- }
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
+ }
8978
10246
  //document.querySelector("#location").value = url
8979
10247
 
8980
10248
  // document.querySelector("#open-location").setAttribute('href', target.href)
@@ -9498,6 +10766,9 @@ const rerenderMenuSection = (container, html) => {
9498
10766
  }
9499
10767
  window.PinokioOpenLogsPage = async (options = {}) => {
9500
10768
  const view = options && options.view === "raw" ? "raw" : "latest"
10769
+ if (window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
10770
+ await window.PinokioCloseOtherMobilePanels("logs")
10771
+ }
9501
10772
  const relativeUrl = buildEmbeddedLogsUrl(view)
9502
10773
  const existingLink = Array.from(document.querySelectorAll('.temp-menu .frame-link')).find(isLogsLink)
9503
10774
  rememberNonLogsSelection(document.querySelector(".frame-link.selected"))
@@ -9762,21 +11033,68 @@ const rerenderMenuSection = (container, html) => {
9762
11033
 
9763
11034
 
9764
11035
 
9765
- const mobileMenuQuery = window.matchMedia ? window.matchMedia("(max-width: 768px)") : null
9766
- const isMobileMenuOpen = () => document.body.classList.contains("mobile-menu-open")
9767
- const appcanvas = document.querySelector(".appcanvas")
9768
- const closeWindowButton = document.querySelector("#close-window")
9769
- const syncMobileBottomNavState = () => {
9770
- const mobileMenuOpen = isMobileMenuOpen()
9771
- 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"))
9772
11087
  const askAiOpen = !!(appcanvas && appcanvas.classList.contains("panel-open"))
9773
11088
  const mobileMenuFallback = document.querySelector(".mobile-menu-fallback")
9774
11089
  const closeSectionVisible = !!(closeWindowButton && !closeWindowButton.classList.contains("hidden"))
9775
11090
 
9776
- document.querySelectorAll(".mobile-nav-menu").forEach((button) => {
9777
- button.classList.toggle("selected", mobileMenuOpen)
9778
- button.setAttribute("aria-expanded", mobileMenuOpen ? "true" : "false")
9779
- })
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
+ }
9780
11098
  document.querySelectorAll(".mobile-nav-community").forEach((button) => {
9781
11099
  button.classList.toggle("selected", communityModeActive)
9782
11100
  button.setAttribute("aria-pressed", communityModeActive ? "true" : "false")
@@ -9797,26 +11115,29 @@ const rerenderMenuSection = (container, html) => {
9797
11115
  mobileMenuFallback.setAttribute("aria-hidden", showFallback ? "false" : "true")
9798
11116
  }
9799
11117
  }
9800
- const setMobileMenuOpen = (next, options = {}) => {
9801
- const shouldOpen = !!next
9802
- if (!mobileMenuQuery || !mobileMenuQuery.matches) {
9803
- document.body.classList.remove("mobile-menu-open")
9804
- syncMobileBottomNavState()
9805
- return
9806
- }
9807
- document.body.classList.toggle("mobile-menu-open", shouldOpen)
9808
- if (shouldOpen && !options.skipRefresh) {
9809
- refresh(false, { nodelay: true })
9810
- }
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
+ }
9811
11131
  syncMobileBottomNavState()
9812
11132
  }
9813
11133
 
9814
- const handleMobileMenuQueryChange = () => {
9815
- if (!mobileMenuQuery || !mobileMenuQuery.matches) {
9816
- document.body.classList.remove("mobile-menu-open")
9817
- }
9818
- syncMobileBottomNavState()
9819
- }
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
+ }
9820
11141
  if (mobileMenuQuery && typeof mobileMenuQuery.addEventListener === "function") {
9821
11142
  mobileMenuQuery.addEventListener("change", handleMobileMenuQueryChange)
9822
11143
  } else if (mobileMenuQuery && typeof mobileMenuQuery.addListener === "function") {
@@ -9832,14 +11153,19 @@ const rerenderMenuSection = (container, html) => {
9832
11153
  setMobileMenuOpen(!isMobileMenuOpen())
9833
11154
  })
9834
11155
  }
9835
- if (document.querySelector("#menu-mobile-close")) {
9836
- document.querySelector("#menu-mobile-close").addEventListener("click", (e) => {
9837
- e.preventDefault()
9838
- setMobileMenuOpen(false, { skipRefresh: true })
9839
- })
9840
- }
9841
- document.querySelectorAll("[data-mobile-proxy]").forEach((trigger) => {
9842
- 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) => {
9843
11169
  const selector = trigger.getAttribute("data-mobile-proxy")
9844
11170
  if (!selector) {
9845
11171
  return
@@ -9852,10 +11178,16 @@ const rerenderMenuSection = (container, html) => {
9852
11178
  if (trigger.getAttribute("data-mobile-close-menu") === "true" && isMobileMenuOpen()) {
9853
11179
  setMobileMenuOpen(false, { skipRefresh: true })
9854
11180
  }
11181
+ await closeOtherMobilePanels(trigger.getAttribute("data-mobile-panel"))
9855
11182
  target.click()
9856
- setTimeout(syncMobileBottomNavState, 0)
9857
- })
9858
- })
11183
+ setTimeout(syncMobileBottomNavState, 0)
11184
+ })
11185
+ })
11186
+ document.addEventListener("keydown", (event) => {
11187
+ if (event.key === "Escape" && isMobileMenuOpen()) {
11188
+ setMobileMenuOpen(false, { skipRefresh: true })
11189
+ }
11190
+ })
9859
11191
  if (appcanvas && typeof MutationObserver === "function") {
9860
11192
  const mobileNavObserver = new MutationObserver(() => {
9861
11193
  syncMobileBottomNavState()
@@ -10821,11 +12153,13 @@ const rerenderMenuSection = (container, html) => {
10821
12153
  refresh()
10822
12154
  }
10823
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
10824
12158
  const frameExists = Array.from(document.querySelectorAll("main.browserview iframe")).some((frame) => {
10825
12159
  return frame.name === rawName
10826
12160
  })
10827
12161
  if (!frameExists) {
10828
- create_iframe(rawName, event.data.launch.href)
12162
+ create_iframe(rawName, launchHref)
10829
12163
  }
10830
12164
  refresh()
10831
12165
  }
@@ -14440,14 +15774,15 @@ const rerenderMenuSection = (container, html) => {
14440
15774
  })
14441
15775
  }
14442
15776
 
14443
- const setChip = (name, visible, text) => {
14444
- roots.forEach((root) => {
14445
- const chip = root.querySelector(`[data-resource-chip="${name}"]`)
14446
- if (!chip) return
14447
- chip.textContent = text
14448
- chip.classList.toggle("hidden", !visible)
14449
- })
14450
- }
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
+ }
14451
15786
 
14452
15787
  const updateFromUsage = (usage) => {
14453
15788
  if (!usage || !usage.ok) {
@@ -14464,9 +15799,10 @@ const rerenderMenuSection = (container, html) => {
14464
15799
  const cpu = metrics.cpu || {}
14465
15800
  const vram = metrics.vram || {}
14466
15801
 
14467
- setChip("ram", !!(ram.enabled && ram.available), `RAM ${ram.formatted || "--"}`)
14468
- setChip("cpu", !!(cpu.enabled && cpu.available && cpu.percent != null), `CPU ${cpu.percent}%`)
14469
- 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 || "--"}`)
14470
15806
 
14471
15807
  if (!usage.running) {
14472
15808
  setStatus("No running app process")
@@ -15008,6 +16344,9 @@ document.addEventListener("DOMContentLoaded", () => {
15008
16344
  const setOpen = (next, opts = {}) => {
15009
16345
  open = !!next
15010
16346
  if (open) {
16347
+ if (window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
16348
+ window.PinokioCloseOtherMobilePanels("ask-ai")
16349
+ }
15011
16350
  const eventDrawer = window.PinokioEventDrawer
15012
16351
  if (eventDrawer && typeof eventDrawer.close === "function") {
15013
16352
  eventDrawer.close()
@@ -15016,7 +16355,9 @@ document.addEventListener("DOMContentLoaded", () => {
15016
16355
  applyDrawerOpenState()
15017
16356
  if (askAiTrigger) {
15018
16357
  askAiTrigger.classList.remove("hidden")
16358
+ askAiTrigger.classList.toggle("selected", open)
15019
16359
  askAiTrigger.setAttribute("aria-hidden", "false")
16360
+ askAiTrigger.setAttribute("aria-expanded", open ? "true" : "false")
15020
16361
  }
15021
16362
  drawer.setAttribute("aria-hidden", open ? "false" : "true")
15022
16363
  if (resizer) {
@@ -15374,7 +16715,7 @@ document.addEventListener("DOMContentLoaded", () => {
15374
16715
  clearPickerList()
15375
16716
  const sourceTools = Array.isArray(tools) ? tools : []
15376
16717
  if (sourceTools.length === 0) {
15377
- setPickerStatus("No launch options available.")
16718
+ setPickerStatus("No shells or plugins available.")
15378
16719
  return
15379
16720
  }
15380
16721
  const normalizedQuery = normalizePickerQuery(query)
@@ -15382,7 +16723,7 @@ document.addEventListener("DOMContentLoaded", () => {
15382
16723
  ? sourceTools.filter((tool) => toolMatchesPickerQuery(tool, normalizedQuery))
15383
16724
  : sourceTools
15384
16725
  if (visibleTools.length === 0) {
15385
- setPickerStatus("No matches.")
16726
+ setPickerStatus("No matching shells or plugins.")
15386
16727
  return
15387
16728
  }
15388
16729
  const groups = new Map()
@@ -15424,7 +16765,7 @@ document.addEventListener("DOMContentLoaded", () => {
15424
16765
  }
15425
16766
  })
15426
16767
  if (!renderedCount) {
15427
- setPickerStatus("No launch options available.")
16768
+ setPickerStatus("No shells or plugins available.")
15428
16769
  return
15429
16770
  }
15430
16771
  setPickerStatus("")
@@ -15480,7 +16821,7 @@ document.addEventListener("DOMContentLoaded", () => {
15480
16821
  if (searchInput) {
15481
16822
  searchInput.value = ""
15482
16823
  }
15483
- setPickerStatus("Loading launch options...")
16824
+ setPickerStatus("Loading shells and plugins...")
15484
16825
  getAskAiTools(workspaceCwd).then((tools) => {
15485
16826
  if (requestId !== pickerRequestId) {
15486
16827
  return
@@ -15770,7 +17111,7 @@ document.addEventListener("DOMContentLoaded", () => {
15770
17111
  setLocation("")
15771
17112
  setActionState(false)
15772
17113
  setEmptyState(true)
15773
- setPickerStatus("Use the Ask AI button to load launch options.")
17114
+ setPickerStatus("Choose a shell or plugin to start an agent.")
15774
17115
  setOpen(false)
15775
17116
  window.PinokioAskAiDrawer = {
15776
17117
  openWithAgent,
@@ -16237,6 +17578,9 @@ document.addEventListener("DOMContentLoaded", () => {
16237
17578
 
16238
17579
  const setOpen = (next, options = {}) => {
16239
17580
  open = !!next
17581
+ if (open && window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
17582
+ window.PinokioCloseOtherMobilePanels("logs")
17583
+ }
16240
17584
  if (appcanvas) {
16241
17585
  appcanvas.classList.toggle("logs-open", open)
16242
17586
  }
@@ -16362,6 +17706,16 @@ document.addEventListener("DOMContentLoaded", () => {
16362
17706
  if (toggle) {
16363
17707
  toggle.addEventListener("click", (event) => {
16364
17708
  event.preventDefault()
17709
+ if (
17710
+ window.PinokioIsLogsPageSelected &&
17711
+ typeof window.PinokioIsLogsPageSelected === "function" &&
17712
+ window.PinokioIsLogsPageSelected() &&
17713
+ window.PinokioCloseLogsPage &&
17714
+ typeof window.PinokioCloseLogsPage === "function"
17715
+ ) {
17716
+ window.PinokioCloseLogsPage()
17717
+ return
17718
+ }
16365
17719
  if (window.PinokioOpenLogsPage && typeof window.PinokioOpenLogsPage === "function") {
16366
17720
  window.PinokioOpenLogsPage({ view: "latest" })
16367
17721
  return
@@ -16455,6 +17809,9 @@ document.addEventListener("DOMContentLoaded", () => {
16455
17809
  return
16456
17810
  }
16457
17811
  communityMode = nextMode
17812
+ if (communityMode && window.PinokioCloseOtherMobilePanels && typeof window.PinokioCloseOtherMobilePanels === "function") {
17813
+ window.PinokioCloseOtherMobilePanels("feed")
17814
+ }
16458
17815
  appcanvas.classList.toggle("community-mode", communityMode)
16459
17816
  if (communityMode) {
16460
17817
  setExpanded(false)
@@ -16804,7 +18161,7 @@ document.addEventListener("DOMContentLoaded", () => {
16804
18161
  }
16805
18162
  if (homeBtn) {
16806
18163
  homeBtn.disabled = false
16807
- setTooltip(homeBtn, "Community home")
18164
+ setTooltip(homeBtn, "Project feed")
16808
18165
  }
16809
18166
  setNavDisabled(false)
16810
18167
  setToggleState(true)
@@ -17041,6 +18398,15 @@ document.addEventListener("DOMContentLoaded", () => {
17041
18398
  setOpen(open, { persist: false })
17042
18399
  updateState()
17043
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
+ }
17044
18410
 
17045
18411
  if (resizer) {
17046
18412
  let isResizing = false