@polderlabs/bizar 5.3.1 → 5.4.1

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 (65) hide show
  1. package/bizar-dash/dist/assets/EnvVarsSection-DhLHZ5ua.js +4 -0
  2. package/bizar-dash/dist/assets/EnvVarsSection-DhLHZ5ua.js.map +1 -0
  3. package/bizar-dash/dist/assets/MobileChat-9UpvDP6-.js +1 -0
  4. package/bizar-dash/dist/assets/{MobileChat-OidrxXR9.js.map → MobileChat-9UpvDP6-.js.map} +1 -1
  5. package/bizar-dash/dist/assets/MobileSettings-BFmN9ZWR.js +1 -0
  6. package/bizar-dash/dist/assets/MobileSettings-BFmN9ZWR.js.map +1 -0
  7. package/bizar-dash/dist/assets/Toast-BlcKl_dN.js +1 -0
  8. package/bizar-dash/dist/assets/Toast-BlcKl_dN.js.map +1 -0
  9. package/bizar-dash/dist/assets/{icons-Bd8piSb2.js → icons-CMPxNV8t.js} +73 -73
  10. package/bizar-dash/dist/assets/icons-CMPxNV8t.js.map +1 -0
  11. package/bizar-dash/dist/assets/main-Dhrvp9Gt.js +16 -0
  12. package/bizar-dash/dist/assets/main-Dhrvp9Gt.js.map +1 -0
  13. package/bizar-dash/dist/assets/{main-3G6mOhiK.css → main-O2tZVdHm.css} +1 -1
  14. package/bizar-dash/dist/assets/mobile-DDY1lquG.js +1 -0
  15. package/bizar-dash/dist/assets/mobile-DDY1lquG.js.map +1 -0
  16. package/bizar-dash/dist/assets/mobile-layout-BjkoHh1W.js +2 -0
  17. package/bizar-dash/dist/assets/mobile-layout-BjkoHh1W.js.map +1 -0
  18. package/bizar-dash/dist/assets/{mobile-CsZQAswA.css → mobile-layout-CJnZNLy3.css} +1 -1
  19. package/bizar-dash/dist/assets/useSlashCommands-eFCiWHVt.js +2 -0
  20. package/bizar-dash/dist/assets/useSlashCommands-eFCiWHVt.js.map +1 -0
  21. package/bizar-dash/dist/index.html +8 -6
  22. package/bizar-dash/dist/mobile.html +4 -4
  23. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  24. package/bizar-dash/src/web/MobileApp.tsx +18 -20
  25. package/bizar-dash/src/web/components/MobileBottomNav.tsx +38 -0
  26. package/bizar-dash/src/web/components/MobileDrawer.tsx +68 -0
  27. package/bizar-dash/src/web/components/MobileHeader.tsx +50 -0
  28. package/bizar-dash/src/web/components/MobileLayout.tsx +63 -0
  29. package/bizar-dash/src/web/components/TaskCard.tsx +69 -0
  30. package/bizar-dash/src/web/components/TaskCreateSheet.tsx +76 -0
  31. package/bizar-dash/src/web/main.tsx +1 -0
  32. package/bizar-dash/src/web/mobile/MobileDoctor.tsx +80 -0
  33. package/bizar-dash/src/web/mobile/MobileEval.tsx +167 -0
  34. package/bizar-dash/src/web/mobile/MobileMarketplace.tsx +106 -0
  35. package/bizar-dash/src/web/mobile/MobileMemory.tsx +108 -0
  36. package/bizar-dash/src/web/mobile/MobileOverview.tsx +213 -0
  37. package/bizar-dash/src/web/mobile/MobilePlugins.tsx +71 -0
  38. package/bizar-dash/src/web/mobile/MobileSettings.tsx +235 -180
  39. package/bizar-dash/src/web/mobile/MobileTasks.tsx +94 -0
  40. package/bizar-dash/src/web/mobile.tsx +1 -0
  41. package/bizar-dash/src/web/styles/main.css +388 -0
  42. package/bizar-dash/src/web/styles/memory.css +45 -0
  43. package/bizar-dash/src/web/styles/mobile-layout.css +233 -0
  44. package/bizar-dash/src/web/styles/mobile.css +180 -0
  45. package/bizar-dash/src/web/styles/settings.css +156 -0
  46. package/bizar-dash/src/web/styles/tasks.css +305 -0
  47. package/bizar-dash/tests/mobile-chat.test.tsx +82 -0
  48. package/bizar-dash/tests/mobile-layout.test.tsx +332 -0
  49. package/bizar-dash/tests/mobile-misc.test.tsx +321 -0
  50. package/bizar-dash/tests/mobile-overview.test.tsx +214 -0
  51. package/bizar-dash/tests/mobile-settings.test.tsx +181 -0
  52. package/bizar-dash/tests/mobile-tasks.test.tsx +162 -0
  53. package/package.json +1 -1
  54. package/bizar-dash/dist/assets/MobileChat-OidrxXR9.js +0 -1
  55. package/bizar-dash/dist/assets/MobileSettings-B91gVFii.js +0 -1
  56. package/bizar-dash/dist/assets/MobileSettings-B91gVFii.js.map +0 -1
  57. package/bizar-dash/dist/assets/icons-Bd8piSb2.js.map +0 -1
  58. package/bizar-dash/dist/assets/main-6YUZY968.js +0 -19
  59. package/bizar-dash/dist/assets/main-6YUZY968.js.map +0 -1
  60. package/bizar-dash/dist/assets/mobile-CSsp30lr.js +0 -2
  61. package/bizar-dash/dist/assets/mobile-CSsp30lr.js.map +0 -1
  62. package/bizar-dash/dist/assets/mobile-DtwK7DOV.js +0 -1
  63. package/bizar-dash/dist/assets/mobile-DtwK7DOV.js.map +0 -1
  64. package/bizar-dash/dist/assets/useSlashCommands-DEkxEvOO.js +0 -2
  65. package/bizar-dash/dist/assets/useSlashCommands-DEkxEvOO.js.map +0 -1
@@ -9749,3 +9749,391 @@ select:focus-visible,
9749
9749
  outline-style: solid;
9750
9750
  }
9751
9751
  }
9752
+
9753
+ /* ─────────────────────────────────────────────────────────────────────
9754
+ v5.4 — Mobile shared list/card styles (Memory, Marketplace, Plugins, Eval, Doctor)
9755
+ ───────────────────────────────────────────────────────────────────── */
9756
+
9757
+ /* Tab bars */
9758
+ .mobile-memory-tabs,
9759
+ .mobile-eval-tabs {
9760
+ display: flex;
9761
+ gap: 6px;
9762
+ margin-bottom: 16px;
9763
+ overflow-x: auto;
9764
+ padding-bottom: 4px;
9765
+ -webkit-overflow-scrolling: touch;
9766
+ }
9767
+
9768
+ .mobile-memory-tab,
9769
+ .mobile-eval-tab {
9770
+ display: flex;
9771
+ align-items: center;
9772
+ gap: 6px;
9773
+ padding: 6px 12px;
9774
+ background: var(--surface-2, var(--bg-elev-2, #1e1e2e));
9775
+ border: 1px solid var(--border, #3a3a4a);
9776
+ border-radius: 14px;
9777
+ color: var(--text-dim, #888);
9778
+ font-size: 12px;
9779
+ font-weight: 500;
9780
+ white-space: nowrap;
9781
+ cursor: pointer;
9782
+ transition: background 120ms, color 120ms, border-color 120ms;
9783
+ }
9784
+
9785
+ .mobile-memory-tab.is-active,
9786
+ .mobile-eval-tab.is-active {
9787
+ background: var(--accent, #8b5cf6);
9788
+ color: #fff;
9789
+ border-color: var(--accent, #8b5cf6);
9790
+ }
9791
+
9792
+ /* Marketplace */
9793
+ .mobile-marketplace {
9794
+ padding: 16px;
9795
+ }
9796
+
9797
+ .mobile-marketplace-search {
9798
+ display: flex;
9799
+ align-items: center;
9800
+ gap: 8px;
9801
+ padding: 10px 14px;
9802
+ background: var(--surface-2, var(--bg-elev-2, #1e1e2e));
9803
+ border: 1px solid var(--border, #3a3a4a);
9804
+ border-radius: 10px;
9805
+ margin-bottom: 16px;
9806
+ color: var(--text-dim, #888);
9807
+ }
9808
+
9809
+ .mobile-marketplace-search input {
9810
+ flex: 1;
9811
+ background: transparent;
9812
+ border: none;
9813
+ color: var(--text, #e0e0e0);
9814
+ font-size: 15px;
9815
+ outline: none;
9816
+ }
9817
+
9818
+ .mobile-marketplace-search input::placeholder {
9819
+ color: var(--text-dim, #888);
9820
+ }
9821
+
9822
+ .mobile-marketplace-list,
9823
+ .mobile-plugins-list,
9824
+ .mobile-eval-runs,
9825
+ .mobile-eval-schedules {
9826
+ display: flex;
9827
+ flex-direction: column;
9828
+ gap: 8px;
9829
+ }
9830
+
9831
+ .mobile-plugin-install-dialog {
9832
+ position: fixed;
9833
+ bottom: 0;
9834
+ left: 0;
9835
+ right: 0;
9836
+ background: var(--surface-1, var(--bg-elev, #18181f));
9837
+ border-top: 1px solid var(--border, #3a3a4a);
9838
+ border-radius: 16px 16px 0 0;
9839
+ padding: 16px;
9840
+ z-index: 200;
9841
+ }
9842
+
9843
+ .mobile-plugin-install-dialog-head {
9844
+ margin-bottom: 16px;
9845
+ }
9846
+
9847
+ .mobile-plugin-install-dialog-head h3 {
9848
+ margin: 0 0 8px;
9849
+ font-size: 17px;
9850
+ font-weight: 600;
9851
+ }
9852
+
9853
+ .mobile-plugin-install-dialog-head p {
9854
+ margin: 0;
9855
+ font-size: 13px;
9856
+ color: var(--text-dim, #888);
9857
+ }
9858
+
9859
+ .mobile-plugin-install-dialog-actions {
9860
+ display: flex;
9861
+ gap: 8px;
9862
+ justify-content: flex-end;
9863
+ }
9864
+
9865
+ /* Plugins */
9866
+ .mobile-plugins {
9867
+ padding: 16px;
9868
+ }
9869
+
9870
+ .mobile-plugins-search {
9871
+ display: flex;
9872
+ align-items: center;
9873
+ gap: 8px;
9874
+ padding: 10px 14px;
9875
+ background: var(--surface-2, var(--bg-elev-2, #1e1e2e));
9876
+ border: 1px solid var(--border, #3a3a4a);
9877
+ border-radius: 10px;
9878
+ margin-bottom: 16px;
9879
+ color: var(--text-dim, #888);
9880
+ }
9881
+
9882
+ .mobile-plugins-search input {
9883
+ flex: 1;
9884
+ background: transparent;
9885
+ border: none;
9886
+ color: var(--text, #e0e0e0);
9887
+ font-size: 15px;
9888
+ outline: none;
9889
+ }
9890
+
9891
+ .mobile-plugins-search input::placeholder {
9892
+ color: var(--text-dim, #888);
9893
+ }
9894
+
9895
+ /* Plugin card */
9896
+ .mobile-plugin-card,
9897
+ .mobile-eval-run-card {
9898
+ background: var(--surface-1, var(--bg-elev, #18181f));
9899
+ border: 1px solid var(--border, #3a3a4a);
9900
+ border-radius: 10px;
9901
+ padding: 12px 14px;
9902
+ }
9903
+
9904
+ .mobile-plugin-card-head {
9905
+ display: flex;
9906
+ align-items: center;
9907
+ justify-content: space-between;
9908
+ margin-bottom: 6px;
9909
+ }
9910
+
9911
+ .mobile-plugin-name {
9912
+ font-size: 15px;
9913
+ font-weight: 600;
9914
+ }
9915
+
9916
+ .mobile-plugin-version {
9917
+ font-size: 11px;
9918
+ color: var(--text-dim, #888);
9919
+ }
9920
+
9921
+ .mobile-plugin-description {
9922
+ margin: 6px 0;
9923
+ font-size: 13px;
9924
+ color: var(--text-dim, #888);
9925
+ line-height: 1.4;
9926
+ }
9927
+
9928
+ .mobile-plugin-stats {
9929
+ font-size: 11px;
9930
+ color: var(--text-dim, #888);
9931
+ margin-top: 6px;
9932
+ }
9933
+
9934
+ /* Eval */
9935
+ .mobile-eval {
9936
+ padding: 16px;
9937
+ }
9938
+
9939
+ .mobile-eval-run-card {
9940
+ display: flex;
9941
+ align-items: center;
9942
+ gap: 12px;
9943
+ cursor: pointer;
9944
+ }
9945
+
9946
+ .mobile-eval-status {
9947
+ width: 56px;
9948
+ height: 56px;
9949
+ border-radius: 50%;
9950
+ display: flex;
9951
+ align-items: center;
9952
+ justify-content: center;
9953
+ font-weight: 700;
9954
+ font-size: 14px;
9955
+ flex-shrink: 0;
9956
+ }
9957
+
9958
+ .mobile-eval-status.is-pass { background: rgba(63, 185, 80, 0.15); color: #3fb950; }
9959
+ .mobile-eval-status.is-warn { background: rgba(210, 153, 34, 0.15); color: #d29922; }
9960
+ .mobile-eval-status.is-fail { background: rgba(239, 68, 68, 0.15); color: #f85149; }
9961
+
9962
+ .mobile-eval-run-info { flex: 1; }
9963
+ .mobile-eval-run-id { font-size: 13px; font-weight: 500; }
9964
+ .mobile-eval-run-time { font-size: 11px; color: var(--text-dim, #888); margin-top: 2px; }
9965
+
9966
+ .mobile-eval-schedule-card {
9967
+ background: var(--surface-1, var(--bg-elev, #18181f));
9968
+ border: 1px solid var(--border, #3a3a4a);
9969
+ border-radius: 10px;
9970
+ padding: 12px 14px;
9971
+ }
9972
+
9973
+ .mobile-eval-schedule-name {
9974
+ font-size: 14px;
9975
+ font-weight: 600;
9976
+ margin-bottom: 4px;
9977
+ }
9978
+
9979
+ .mobile-eval-schedule-meta {
9980
+ font-size: 12px;
9981
+ color: var(--text-dim, #888);
9982
+ }
9983
+
9984
+ .mobile-eval-run-sheet {
9985
+ position: fixed;
9986
+ bottom: 0;
9987
+ left: 0;
9988
+ right: 0;
9989
+ background: var(--surface-1, var(--bg-elev, #18181f));
9990
+ border-top: 1px solid var(--border, #3a3a4a);
9991
+ border-radius: 16px 16px 0 0;
9992
+ padding: 16px;
9993
+ z-index: 200;
9994
+ }
9995
+
9996
+ .mobile-bottom-sheet-header {
9997
+ display: flex;
9998
+ align-items: center;
9999
+ justify-content: space-between;
10000
+ margin-bottom: 16px;
10001
+ }
10002
+
10003
+ .mobile-bottom-sheet-header h3 {
10004
+ margin: 0;
10005
+ font-size: 17px;
10006
+ font-weight: 600;
10007
+ }
10008
+
10009
+ .mobile-bottom-sheet-close {
10010
+ background: none;
10011
+ border: none;
10012
+ color: var(--text-dim, #888);
10013
+ font-size: 24px;
10014
+ cursor: pointer;
10015
+ padding: 0;
10016
+ line-height: 1;
10017
+ }
10018
+
10019
+ .mobile-eval-run-sheet-body {
10020
+ display: flex;
10021
+ flex-direction: column;
10022
+ gap: 10px;
10023
+ }
10024
+
10025
+ .mobile-eval-run-sheet-row {
10026
+ display: flex;
10027
+ justify-content: space-between;
10028
+ font-size: 14px;
10029
+ padding: 8px 0;
10030
+ border-bottom: 1px solid var(--border, #3a3a4a);
10031
+ }
10032
+
10033
+ .mobile-eval-run-sheet-row:last-child {
10034
+ border-bottom: none;
10035
+ }
10036
+
10037
+ .mobile-eval-run-sheet-row span:first-child {
10038
+ color: var(--text-dim, #888);
10039
+ }
10040
+
10041
+ /* Doctor */
10042
+ .mobile-doctor {
10043
+ padding: 16px;
10044
+ display: flex;
10045
+ flex-direction: column;
10046
+ gap: 16px;
10047
+ }
10048
+
10049
+ .mobile-doctor-status {
10050
+ text-align: center;
10051
+ padding: 32px 16px;
10052
+ background: var(--surface-1, var(--bg-elev, #18181f));
10053
+ border: 1px solid var(--border, #3a3a4a);
10054
+ border-radius: 14px;
10055
+ color: var(--text-dim, #888);
10056
+ }
10057
+
10058
+ .mobile-doctor-status.is-ok { border-color: rgba(63, 185, 80, 0.4); color: #3fb950; }
10059
+ .mobile-doctor-status.is-warn { border-color: rgba(210, 153, 34, 0.4); color: #d29922; }
10060
+ .mobile-doctor-status.is-fail { border-color: rgba(239, 68, 68, 0.4); color: #f85149; }
10061
+
10062
+ .mobile-doctor-status-text {
10063
+ font-size: 24px;
10064
+ font-weight: 700;
10065
+ letter-spacing: 0.05em;
10066
+ margin-top: 12px;
10067
+ color: var(--text, #e0e0e0);
10068
+ }
10069
+
10070
+ .mobile-doctor-status-sub {
10071
+ font-size: 12px;
10072
+ color: var(--text-dim, #888);
10073
+ margin-top: 4px;
10074
+ }
10075
+
10076
+ .mobile-doctor-issues {
10077
+ background: var(--surface-1, var(--bg-elev, #18181f));
10078
+ border: 1px solid var(--border, #3a3a4a);
10079
+ border-radius: 10px;
10080
+ padding: 16px;
10081
+ }
10082
+
10083
+ .mobile-doctor-issues h3 {
10084
+ margin: 0 0 12px;
10085
+ font-size: 14px;
10086
+ font-weight: 600;
10087
+ }
10088
+
10089
+ .mobile-doctor-issue {
10090
+ display: flex;
10091
+ gap: 10px;
10092
+ padding: 10px;
10093
+ background: var(--surface-2, var(--bg-elev-2, #1e1e2e));
10094
+ border-radius: 8px;
10095
+ margin-bottom: 6px;
10096
+ border-left: 3px solid;
10097
+ }
10098
+
10099
+ .mobile-doctor-issue.is-warn { border-left-color: #d29922; color: #d29922; }
10100
+ .mobile-doctor-issue.is-fail { border-left-color: #f85149; color: #f85149; }
10101
+ .mobile-doctor-issue.is-ok { border-left-color: #3fb950; color: #3fb950; }
10102
+
10103
+ .mobile-doctor-issue-name { font-size: 13px; font-weight: 500; color: var(--text, #e0e0e0); }
10104
+ .mobile-doctor-issue-msg { font-size: 12px; color: var(--text-dim, #888); margin-top: 2px; }
10105
+
10106
+ .mobile-doctor-ok {
10107
+ display: flex;
10108
+ flex-direction: column;
10109
+ align-items: center;
10110
+ gap: 8px;
10111
+ padding: 32px 16px;
10112
+ background: var(--surface-1, var(--bg-elev, #18181f));
10113
+ border: 1px solid rgba(63, 185, 80, 0.4);
10114
+ border-radius: 14px;
10115
+ color: #3fb950;
10116
+ text-align: center;
10117
+ }
10118
+
10119
+ .mobile-doctor-ok p {
10120
+ margin: 0;
10121
+ font-size: 15px;
10122
+ color: var(--text, #e0e0e0);
10123
+ }
10124
+
10125
+ /* Mobile empty state */
10126
+ .mobile-empty {
10127
+ display: flex;
10128
+ flex-direction: column;
10129
+ align-items: center;
10130
+ gap: 8px;
10131
+ padding: 48px 16px;
10132
+ color: var(--text-dim, #888);
10133
+ text-align: center;
10134
+ }
10135
+
10136
+ .mobile-empty p {
10137
+ margin: 0;
10138
+ font-size: 14px;
10139
+ }
@@ -1118,3 +1118,48 @@ dl.memory-config-row dd {
1118
1118
  margin: 0;
1119
1119
  font-style: italic;
1120
1120
  }
1121
+
1122
+ /* ─────────────────────────────────────────────────────────────────────
1123
+ v5.4 — Mobile Memory view
1124
+ ───────────────────────────────────────────────────────────────────── */
1125
+
1126
+ .mobile-memory {
1127
+ padding: 16px;
1128
+ }
1129
+
1130
+ .mobile-memory-tabs {
1131
+ display: flex;
1132
+ gap: 6px;
1133
+ margin-bottom: 16px;
1134
+ overflow-x: auto;
1135
+ padding-bottom: 4px;
1136
+ -webkit-overflow-scrolling: touch;
1137
+ }
1138
+
1139
+ .mobile-memory-tab {
1140
+ display: flex;
1141
+ align-items: center;
1142
+ gap: 6px;
1143
+ padding: 6px 12px;
1144
+ background: var(--surface-2, var(--bg-elev-2, #1e1e2e));
1145
+ border: 1px solid var(--border, #3a3a4a);
1146
+ border-radius: 14px;
1147
+ color: var(--text-dim, #888);
1148
+ font-size: 12px;
1149
+ font-weight: 500;
1150
+ white-space: nowrap;
1151
+ cursor: pointer;
1152
+ transition: background 120ms, color 120ms, border-color 120ms;
1153
+ }
1154
+
1155
+ .mobile-memory-tab.is-active {
1156
+ background: var(--accent, #8b5cf6);
1157
+ color: #fff;
1158
+ border-color: var(--accent, #8b5cf6);
1159
+ }
1160
+
1161
+ .mobile-memory-content {
1162
+ display: flex;
1163
+ flex-direction: column;
1164
+ gap: 12px;
1165
+ }
@@ -0,0 +1,233 @@
1
+ /* ─────────────────────────────────────────────────────────────────────
2
+ Mobile Layout Shell — v5.4
3
+ Mobile-first navigation: header, drawer, content, bottom nav.
4
+ ───────────────────────────────────────────────────────────────────── */
5
+
6
+ /* ─── Layout shell ─────────────────────────────────────────────────── */
7
+ .mobile-layout {
8
+ display: flex;
9
+ flex-direction: column;
10
+ height: 100vh;
11
+ height: 100dvh;
12
+ overflow: hidden;
13
+ background: var(--bg);
14
+ }
15
+
16
+ /* ─── Header ──────────────────────────────────────────────────────── */
17
+ .mobile-header {
18
+ position: sticky;
19
+ top: 0;
20
+ z-index: 100;
21
+ display: flex;
22
+ align-items: center;
23
+ gap: 12px;
24
+ height: 56px;
25
+ padding: 0 16px;
26
+ background: var(--surface-1, var(--surface, var(--bg-elev)));
27
+ border-bottom: 1px solid transparent;
28
+ transition: border-color 200ms ease;
29
+ }
30
+
31
+ .mobile-header.is-scrolled {
32
+ border-bottom-color: var(--border);
33
+ }
34
+
35
+ .mobile-header-title {
36
+ flex: 1;
37
+ font-size: 18px;
38
+ font-weight: 600;
39
+ margin: 0;
40
+ color: var(--text-strong, var(--text));
41
+ }
42
+
43
+ .mobile-menu-btn,
44
+ .mobile-search-btn,
45
+ .mobile-settings-exit {
46
+ background: transparent;
47
+ border: none;
48
+ color: var(--text);
49
+ padding: 8px;
50
+ border-radius: 8px;
51
+ cursor: pointer;
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ transition: background 120ms ease;
56
+ }
57
+
58
+ .mobile-menu-btn:hover,
59
+ .mobile-search-btn:hover,
60
+ .mobile-settings-exit:hover {
61
+ background: var(--bg-elev-2, var(--bg-elev));
62
+ }
63
+
64
+ .mobile-menu-btn:active,
65
+ .mobile-search-btn:active,
66
+ .mobile-settings-exit:active {
67
+ background: var(--bg-elev-3);
68
+ }
69
+
70
+ /* ─── Content area ───────────────────────────────────────────────── */
71
+ .mobile-content {
72
+ flex: 1 1 auto;
73
+ min-height: 0;
74
+ overflow-y: auto;
75
+ overflow-x: hidden;
76
+ padding: 12px 16px 80px;
77
+ -webkit-overflow-scrolling: touch;
78
+ overscroll-behavior: contain;
79
+ }
80
+
81
+ /* ─── Bottom nav ──────────────────────────────────────────────────── */
82
+ .mobile-bottom-nav {
83
+ position: fixed;
84
+ bottom: 0;
85
+ left: 0;
86
+ right: 0;
87
+ display: flex;
88
+ height: 64px;
89
+ background: var(--surface-1, var(--surface, var(--bg-elev)));
90
+ border-top: 1px solid var(--border);
91
+ z-index: 50;
92
+ padding-bottom: env(safe-area-inset-bottom, 0);
93
+ }
94
+
95
+ .mobile-nav-item {
96
+ flex: 1;
97
+ display: flex;
98
+ flex-direction: column;
99
+ align-items: center;
100
+ justify-content: center;
101
+ gap: 4px;
102
+ background: transparent;
103
+ border: none;
104
+ color: var(--text-dim, var(--text-muted));
105
+ font-size: 10px;
106
+ font-family: inherit;
107
+ cursor: pointer;
108
+ padding: 4px 0;
109
+ transition: color 120ms ease;
110
+ }
111
+
112
+ .mobile-nav-item.is-active {
113
+ color: var(--accent);
114
+ }
115
+
116
+ .mobile-nav-label {
117
+ font-size: 10px;
118
+ font-weight: 500;
119
+ line-height: 1;
120
+ }
121
+
122
+ /* ─── Drawer overlay ─────────────────────────────────────────────── */
123
+ .mobile-drawer-overlay {
124
+ position: fixed;
125
+ inset: 0;
126
+ background: rgba(0, 0, 0, 0.5);
127
+ z-index: 60;
128
+ animation: fadeIn 200ms ease;
129
+ }
130
+
131
+ /* ─── Drawer panel ───────────────────────────────────────────────── */
132
+ .mobile-drawer {
133
+ position: fixed;
134
+ top: 0;
135
+ left: 0;
136
+ bottom: 0;
137
+ width: 80%;
138
+ max-width: 320px;
139
+ background: var(--surface-1, var(--surface, var(--bg-elev)));
140
+ z-index: 70;
141
+ transform: translateX(-100%);
142
+ transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
143
+ overflow-y: auto;
144
+ -webkit-overflow-scrolling: touch;
145
+ display: flex;
146
+ flex-direction: column;
147
+ }
148
+
149
+ .mobile-drawer.is-open {
150
+ transform: translateX(0);
151
+ }
152
+
153
+ .mobile-drawer-head {
154
+ position: sticky;
155
+ top: 0;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: space-between;
159
+ padding: 16px;
160
+ background: var(--surface-1, var(--surface, var(--bg-elev)));
161
+ border-bottom: 1px solid var(--border);
162
+ flex-shrink: 0;
163
+ }
164
+
165
+ .mobile-drawer-head h2 {
166
+ font-size: 18px;
167
+ font-weight: 600;
168
+ margin: 0;
169
+ color: var(--text-strong, var(--text));
170
+ }
171
+
172
+ .mobile-drawer-close {
173
+ background: transparent;
174
+ border: none;
175
+ color: var(--text);
176
+ padding: 8px;
177
+ border-radius: 8px;
178
+ cursor: pointer;
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ }
183
+
184
+ .mobile-drawer-grid {
185
+ display: grid;
186
+ grid-template-columns: repeat(2, 1fr);
187
+ gap: 8px;
188
+ padding: 16px;
189
+ flex: 1;
190
+ }
191
+
192
+ .mobile-drawer-item {
193
+ display: flex;
194
+ flex-direction: column;
195
+ align-items: center;
196
+ justify-content: center;
197
+ gap: 8px;
198
+ padding: 16px 8px;
199
+ background: var(--surface-2, var(--bg-elev-2));
200
+ border: 1px solid var(--border);
201
+ border-radius: 8px;
202
+ color: var(--text);
203
+ font-size: 12px;
204
+ font-family: inherit;
205
+ cursor: pointer;
206
+ min-height: 80px;
207
+ transition: border-color 120ms ease, background 120ms ease;
208
+ }
209
+
210
+ .mobile-drawer-item.is-active {
211
+ border-color: var(--accent);
212
+ background: rgba(139, 92, 246, 0.1);
213
+ }
214
+
215
+ .mobile-drawer-item:active {
216
+ opacity: 0.8;
217
+ }
218
+
219
+ /* ─── Animations ─────────────────────────────────────────────────── */
220
+ @keyframes fadeIn {
221
+ from { opacity: 0; }
222
+ to { opacity: 1; }
223
+ }
224
+
225
+ /* ─── Desktop hide ───────────────────────────────────────────────── */
226
+ @media (min-width: 1024px) {
227
+ .mobile-layout,
228
+ .mobile-bottom-nav,
229
+ .mobile-drawer,
230
+ .mobile-header {
231
+ display: none;
232
+ }
233
+ }