pal-code 0.1.0__py3-none-any.whl

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 (282) hide show
  1. pal/__init__.py +29 -0
  2. pal/__main__.py +3 -0
  3. pal/access_manager/__init__.py +16 -0
  4. pal/access_manager/components/__init__.py +14 -0
  5. pal/access_manager/components/access_control.py +41 -0
  6. pal/access_manager/components/base.py +39 -0
  7. pal/access_manager/components/intervention.py +31 -0
  8. pal/access_manager/components/privilege_registry.py +30 -0
  9. pal/access_manager/pipeline.py +68 -0
  10. pal/access_manager/utils/__init__.py +2 -0
  11. pal/agent_constraints/__init__.py +3 -0
  12. pal/agent_constraints/components/AGENT_OUTPUT.md +13 -0
  13. pal/agent_constraints/components/__init__.py +3 -0
  14. pal/agent_constraints/components/constraints.py +22 -0
  15. pal/agent_constraints/pipeline.py +22 -0
  16. pal/agent_constraints/utils/__init__.py +2 -0
  17. pal/agents/__init__.py +12 -0
  18. pal/agents/coding.py +14 -0
  19. pal/agents/docs.py +15 -0
  20. pal/chat/__init__.py +4 -0
  21. pal/chat/demo.py +231 -0
  22. pal/chat/providers.py +23 -0
  23. pal/chat/service.py +591 -0
  24. pal/chat/services/__init__.py +26 -0
  25. pal/chat/services/base.py +142 -0
  26. pal/chat/services/data.py +142 -0
  27. pal/chat/services/media.py +123 -0
  28. pal/chat/services/web.py +60 -0
  29. pal/chat/sessions.py +108 -0
  30. pal/chat/tools.py +446 -0
  31. pal/chat/uploads.py +81 -0
  32. pal/cli.py +502 -0
  33. pal/compression/__init__.py +12 -0
  34. pal/compression/components/__init__.py +64 -0
  35. pal/compression/components/adverbs.py +20 -0
  36. pal/compression/components/hedges.py +54 -0
  37. pal/compression/components/interjections.py +20 -0
  38. pal/compression/components/minifier.py +56 -0
  39. pal/compression/components/output_compressor.py +13 -0
  40. pal/compression/components/pleonasms.py +54 -0
  41. pal/compression/components/punctuations.py +36 -0
  42. pal/compression/components/stopwords.py +62 -0
  43. pal/compression/history.py +346 -0
  44. pal/compression/pipeline.py +58 -0
  45. pal/compression/utils/__init__.py +30 -0
  46. pal/compression/utils/negations.py +18 -0
  47. pal/compression/utils/nltk_setup.py +20 -0
  48. pal/compression/utils/pronouns.py +27 -0
  49. pal/compression/utils/proselint_setup.py +9 -0
  50. pal/compression/utils/spacy_setup.py +22 -0
  51. pal/config/default.yaml +163 -0
  52. pal/config.py +504 -0
  53. pal/context_manager/__init__.py +7 -0
  54. pal/context_manager/chat_context.py +117 -0
  55. pal/context_manager/components/__init__.py +5 -0
  56. pal/context_manager/components/assembler.py +75 -0
  57. pal/context_manager/components/context_cache.py +45 -0
  58. pal/context_manager/components/kv_bridge.py +16 -0
  59. pal/context_manager/components/pager.py +48 -0
  60. pal/context_manager/components/simple_context_manager.py +56 -0
  61. pal/context_manager/components/turns.py +88 -0
  62. pal/context_manager/pipeline.py +27 -0
  63. pal/context_manager/utils/__init__.py +18 -0
  64. pal/context_manager/utils/hashing.py +5 -0
  65. pal/context_manager/utils/relevance.py +59 -0
  66. pal/context_manager/utils/storage.py +37 -0
  67. pal/documents/__init__.py +4 -0
  68. pal/documents/components/__init__.py +0 -0
  69. pal/documents/components/chunker.py +79 -0
  70. pal/documents/components/index.py +155 -0
  71. pal/documents/utils/__init__.py +1 -0
  72. pal/errors.py +40 -0
  73. pal/input_converters/__init__.py +8 -0
  74. pal/input_converters/components/__init__.py +0 -0
  75. pal/input_converters/components/base.py +38 -0
  76. pal/input_converters/components/pandoc_converter.py +87 -0
  77. pal/input_converters/components/pdf_converter.py +46 -0
  78. pal/input_converters/components/pptx_converter.py +52 -0
  79. pal/input_converters/components/xlsx_converter.py +38 -0
  80. pal/input_converters/pipeline.py +72 -0
  81. pal/input_converters/utils/__init__.py +1 -0
  82. pal/input_converters/workspace.py +56 -0
  83. pal/input_savers/INPUT_RULES.md +2 -0
  84. pal/input_savers/__init__.py +5 -0
  85. pal/input_savers/components/__init__.py +0 -0
  86. pal/input_savers/components/base.py +40 -0
  87. pal/input_savers/components/methods.py +41 -0
  88. pal/input_savers/components/verifier.py +39 -0
  89. pal/input_savers/pipeline.py +154 -0
  90. pal/input_savers/utils/__init__.py +0 -0
  91. pal/input_savers/utils/guards.py +94 -0
  92. pal/knowledge_graph/__init__.py +10 -0
  93. pal/knowledge_graph/components/__init__.py +0 -0
  94. pal/knowledge_graph/components/base.py +50 -0
  95. pal/knowledge_graph/components/builder.py +54 -0
  96. pal/knowledge_graph/components/retriever.py +100 -0
  97. pal/knowledge_graph/components/workspace.py +116 -0
  98. pal/knowledge_graph/pipeline.py +215 -0
  99. pal/knowledge_graph/utils/__init__.py +1 -0
  100. pal/latency_tracker/__init__.py +3 -0
  101. pal/latency_tracker/pipeline.py +86 -0
  102. pal/llm_scheduler/__init__.py +11 -0
  103. pal/llm_scheduler/api.py +137 -0
  104. pal/llm_scheduler/code.py +28 -0
  105. pal/llm_scheduler/core.py +92 -0
  106. pal/llm_scheduler/local.py +215 -0
  107. pal/llm_scheduler/pipeline.py +42 -0
  108. pal/llm_scheduler/types.py +92 -0
  109. pal/llm_wrapper/__init__.py +34 -0
  110. pal/llm_wrapper/adapter.py +316 -0
  111. pal/llm_wrapper/components/__init__.py +23 -0
  112. pal/llm_wrapper/components/adapter_types.py +90 -0
  113. pal/llm_wrapper/components/base.py +195 -0
  114. pal/llm_wrapper/components/features.py +104 -0
  115. pal/llm_wrapper/components/litellm_wrapper.py +215 -0
  116. pal/llm_wrapper/components/openrouter_wrapper.py +114 -0
  117. pal/llm_wrapper/modes.py +73 -0
  118. pal/llm_wrapper/pipeline.py +61 -0
  119. pal/llm_wrapper/utils/__init__.py +4 -0
  120. pal/llm_wrapper/utils/registry.py +49 -0
  121. pal/llm_wrapper/utils/token_counting.py +10 -0
  122. pal/local_llm/__init__.py +5 -0
  123. pal/local_llm/components/__init__.py +0 -0
  124. pal/local_llm/components/huggingface_local.py +217 -0
  125. pal/local_llm/components/local_llm.py +60 -0
  126. pal/logging_setup.py +18 -0
  127. pal/memory/__init__.py +7 -0
  128. pal/memory/components/__init__.py +6 -0
  129. pal/memory/components/lru_k.py +56 -0
  130. pal/memory/components/manager.py +98 -0
  131. pal/memory/components/note.py +54 -0
  132. pal/memory/components/storage_manager.py +60 -0
  133. pal/memory/pipeline.py +122 -0
  134. pal/memory/utils/__init__.py +3 -0
  135. pal/memory/utils/keyword_overlap.py +3 -0
  136. pal/memory_tracker/__init__.py +3 -0
  137. pal/memory_tracker/components/__init__.py +0 -0
  138. pal/memory_tracker/components/process.py +56 -0
  139. pal/memory_tracker/pipeline.py +44 -0
  140. pal/metrics/__init__.py +4 -0
  141. pal/metrics/components/__init__.py +4 -0
  142. pal/metrics/components/collector.py +140 -0
  143. pal/metrics/components/exporter.py +28 -0
  144. pal/metrics/pipeline.py +49 -0
  145. pal/metrics/utils/__init__.py +2 -0
  146. pal/notes_manager/__init__.py +5 -0
  147. pal/notes_manager/components/__init__.py +0 -0
  148. pal/notes_manager/components/privacy.py +14 -0
  149. pal/notes_manager/components/recall.py +31 -0
  150. pal/notes_manager/components/tidy.py +28 -0
  151. pal/notes_manager/pipeline.py +138 -0
  152. pal/orchestrator/__init__.py +26 -0
  153. pal/orchestrator/components/__init__.py +26 -0
  154. pal/orchestrator/components/agent.py +105 -0
  155. pal/orchestrator/components/cgroup_manager.py +209 -0
  156. pal/orchestrator/components/context_interrupt.py +220 -0
  157. pal/orchestrator/components/limits.py +9 -0
  158. pal/orchestrator/components/scheduler.py +69 -0
  159. pal/orchestrator/components/syscall_scheduler.py +200 -0
  160. pal/orchestrator/pipeline.py +228 -0
  161. pal/orchestrator/utils/__init__.py +4 -0
  162. pal/orchestrator/utils/device.py +164 -0
  163. pal/orchestrator/utils/protocol.py +32 -0
  164. pal/os_kernel/__init__.py +5 -0
  165. pal/os_kernel/filesystem.py +80 -0
  166. pal/os_kernel/network.py +146 -0
  167. pal/os_kernel/pipeline.py +175 -0
  168. pal/os_kernel/sysinfo.py +36 -0
  169. pal/paths.py +59 -0
  170. pal/pipeline.py +177 -0
  171. pal/py.typed +0 -0
  172. pal/redact.py +19 -0
  173. pal/sdk/__init__.py +33 -0
  174. pal/sdk/adapters.py +43 -0
  175. pal/sdk/agent.py +99 -0
  176. pal/sdk/components/__init__.py +14 -0
  177. pal/sdk/components/autogen_adapter.py +65 -0
  178. pal/sdk/components/autogen_client.py +98 -0
  179. pal/sdk/components/framework_adapter_base.py +69 -0
  180. pal/sdk/components/metagpt_adapter.py +46 -0
  181. pal/sdk/components/open_interpreter_adapter.py +47 -0
  182. pal/sdk/components/tool_catalog.py +44 -0
  183. pal/sdk/os_api.py +84 -0
  184. pal/sdk/patterns.py +129 -0
  185. pal/sdk/pipeline.py +240 -0
  186. pal/sdk/queries.py +68 -0
  187. pal/sdk/savers.py +88 -0
  188. pal/sdk/utils/__init__.py +2 -0
  189. pal/storage_manager/__init__.py +17 -0
  190. pal/storage_manager/components/__init__.py +19 -0
  191. pal/storage_manager/components/base.py +50 -0
  192. pal/storage_manager/components/local_file_backend.py +84 -0
  193. pal/storage_manager/components/storage_queue.py +91 -0
  194. pal/storage_manager/components/vector_store_backend.py +122 -0
  195. pal/storage_manager/pipeline.py +153 -0
  196. pal/storage_manager/utils/__init__.py +4 -0
  197. pal/storage_manager/utils/memory_adapter.py +60 -0
  198. pal/storage_manager/utils/sdk.py +93 -0
  199. pal/studio/__init__.py +0 -0
  200. pal/studio/builder.py +166 -0
  201. pal/studio/catalog.py +90 -0
  202. pal/studio/checks.py +129 -0
  203. pal/studio/clients.py +6 -0
  204. pal/studio/editor.py +137 -0
  205. pal/studio/files.py +6 -0
  206. pal/studio/models.py +6 -0
  207. pal/studio/plan.py +149 -0
  208. pal/studio/planner.py +205 -0
  209. pal/studio/policy.py +69 -0
  210. pal/studio/routes.py +254 -0
  211. pal/studio/runs.py +210 -0
  212. pal/task_router/__init__.py +11 -0
  213. pal/task_router/components/__init__.py +0 -0
  214. pal/task_router/components/answerer.py +37 -0
  215. pal/task_router/components/base.py +34 -0
  216. pal/task_router/components/classifier.py +40 -0
  217. pal/task_router/components/gates.py +23 -0
  218. pal/task_router/pipeline.py +61 -0
  219. pal/task_router/utils/__init__.py +1 -0
  220. pal/terminal/__init__.py +1 -0
  221. pal/terminal/backend.py +141 -0
  222. pal/terminal/bench.py +173 -0
  223. pal/terminal/cli.py +826 -0
  224. pal/terminal/clients.py +170 -0
  225. pal/terminal/commands.py +401 -0
  226. pal/terminal/decide.py +242 -0
  227. pal/terminal/files.py +55 -0
  228. pal/terminal/flow_cli.py +439 -0
  229. pal/terminal/hardware.py +199 -0
  230. pal/terminal/history.py +88 -0
  231. pal/terminal/keys.py +83 -0
  232. pal/terminal/local_models.py +261 -0
  233. pal/terminal/logo.py +117 -0
  234. pal/terminal/models.py +99 -0
  235. pal/terminal/policy.py +54 -0
  236. pal/terminal/project.py +413 -0
  237. pal/terminal/review.py +65 -0
  238. pal/terminal/security.py +239 -0
  239. pal/terminal/session.py +503 -0
  240. pal/terminal/setup.py +354 -0
  241. pal/terminal/syntax.py +98 -0
  242. pal/terminal/theme.py +37 -0
  243. pal/terminal/ui.py +647 -0
  244. pal/terminal/voice.py +137 -0
  245. pal/terminal/workflow.py +624 -0
  246. pal/token_tracker/__init__.py +3 -0
  247. pal/token_tracker/pipeline.py +54 -0
  248. pal/tokens.py +21 -0
  249. pal/tool_catalog.py +107 -0
  250. pal/tool_manager/__init__.py +17 -0
  251. pal/tool_manager/builtin.py +82 -0
  252. pal/tool_manager/components/__init__.py +19 -0
  253. pal/tool_manager/components/base.py +53 -0
  254. pal/tool_manager/components/conflict_resolver.py +27 -0
  255. pal/tool_manager/components/param_validator.py +41 -0
  256. pal/tool_manager/components/tool_call_queue.py +111 -0
  257. pal/tool_manager/components/tool_registry.py +60 -0
  258. pal/tool_manager/pipeline.py +80 -0
  259. pal/tool_manager/utils/__init__.py +3 -0
  260. pal/web/__init__.py +3 -0
  261. pal/web/app.py +276 -0
  262. pal/web/static/editor.js +219 -0
  263. pal/web/static/fonts/LICENSE-Inter.txt +3 -0
  264. pal/web/static/fonts/inter-400.woff2 +0 -0
  265. pal/web/static/fonts/inter-500.woff2 +0 -0
  266. pal/web/static/fonts/inter-600.woff2 +0 -0
  267. pal/web/static/fonts/inter-700.woff2 +0 -0
  268. pal/web/static/inter.css +5 -0
  269. pal/web/static/pal-logo-256.png +0 -0
  270. pal/web/static/pal-logo-32.png +0 -0
  271. pal/web/static/pal-logo-64.png +0 -0
  272. pal/web/static/studio.css +306 -0
  273. pal/web/static/studio.js +533 -0
  274. pal/web/static/voice.js +76 -0
  275. pal/web/templates/index.html +368 -0
  276. pal/web/templates/studio.html +120 -0
  277. pal_code-0.1.0.dist-info/METADATA +379 -0
  278. pal_code-0.1.0.dist-info/RECORD +282 -0
  279. pal_code-0.1.0.dist-info/WHEEL +5 -0
  280. pal_code-0.1.0.dist-info/entry_points.txt +2 -0
  281. pal_code-0.1.0.dist-info/licenses/LICENSE +21 -0
  282. pal_code-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,306 @@
1
+ :root{color-scheme:dark;--red:#E50914;--red-dark:#B20710;--red-hi:#FF4D57;--red-tint:rgba(229,9,20,.16);--red-soft:#1a1a1a;--surface:#141414;--ink:#fff;--muted:#a3a3a3;--line:#2e2e2e;--bg:#000;--ok:#FF4D57;--bad:#FF4D57}
2
+ *{box-sizing:border-box}
3
+ html,body{height:100%;margin:0}
4
+ body{background:var(--bg);color:var(--ink);font:15px/1.5 "Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
5
+ .shell{display:flex;height:100%}
6
+ .sr{position:absolute;left:-9999px}
7
+ .sp{flex:1}
8
+ .hint{color:var(--muted);font-size:12px;margin:4px 0}
9
+ .warn{color:var(--red-hi);font-size:13px}
10
+ :focus-visible{outline:2px solid var(--red);outline-offset:2px}
11
+ button,select,input[type=text],input[type=password],textarea{font:inherit;color:var(--ink)}
12
+ button{cursor:pointer}button:disabled{opacity:.45;cursor:default}
13
+
14
+ /* sidebar */
15
+ .side{width:248px;flex:none;border-right:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;padding:14px 10px}
16
+ .brand{display:flex;align-items:center;gap:10px;padding:2px 8px 14px}
17
+ .mark{width:28px;height:28px;border-radius:8px;background:var(--red);color:#fff;font-weight:800;display:grid;place-items:center}
18
+ .brandname{font-weight:700;letter-spacing:.2px}
19
+ nav{flex:1;min-height:0;overflow:auto}
20
+ .navitem{display:flex;gap:10px;align-items:center;width:100%;text-align:left;border:0;background:none;border-radius:8px;padding:8px 10px;color:var(--ink);text-decoration:none;font-size:14px}
21
+ .navitem:hover{background:var(--red-soft)}
22
+ .navitem.active{background:var(--red-tint);color:var(--red-hi);font-weight:600}
23
+ .ico{width:18px;text-align:center;color:var(--red)}
24
+ .navhead{font-size:12px;color:var(--muted);margin:18px 10px 4px}
25
+ .navnote{font-size:12px;color:var(--muted);margin:2px 10px}
26
+ .runs{display:flex;flex-direction:column;gap:2px}
27
+ .runitem{border:0;background:none;text-align:left;border-radius:8px;padding:6px 10px;font-size:13px;display:flex;gap:8px;align-items:center}
28
+ .runitem:hover{background:var(--red-soft)}
29
+ .dot{width:8px;height:8px;border-radius:50%;background:var(--line);flex:none}
30
+ .dot.live{background:var(--red)}.dot.done{background:var(--ink)}
31
+ .sidefoot{padding:8px}
32
+ .chip{display:inline-block;border:1px solid var(--line);border-radius:14px;padding:3px 10px;font-size:12px;background:var(--surface);color:var(--muted)}
33
+ .chip.ok{border-color:var(--red);color:var(--red-hi)}.chip.bad{border-color:var(--red-hi);background:var(--red-tint);color:var(--red-hi)}
34
+
35
+ /* main */
36
+ .mainwrap{flex:1;min-width:0;display:flex;flex-direction:column}
37
+ .top{display:none;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid var(--line)}
38
+ .toptitle{font-weight:600}
39
+ .iconbtn{width:36px;height:36px;border-radius:50%;border:1px solid var(--line);background:var(--surface);display:grid;place-items:center;font-size:20px;line-height:1;color:var(--ink)}
40
+ .iconbtn:hover:not(:disabled){border-color:var(--red);color:var(--red)}
41
+ .iconbtn.live{background:var(--red);border-color:var(--red);color:#fff;animation:pulse 1.2s infinite}
42
+ @keyframes pulse{0%{box-shadow:0 0 0 0 rgba(230,26,39,.45)}100%{box-shadow:0 0 0 12px rgba(230,26,39,0)}}
43
+ .main{flex:1;min-height:0;overflow:auto;padding:24px 20px 8px}
44
+ .empty{max-width:820px;margin:6vh auto 0;text-align:center}
45
+ .empty h1{font-size:30px;margin:0 0 6px;font-weight:700}
46
+ .lead{color:var(--muted);margin:0 auto 26px;max-width:560px}
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+ .ghost{border:1px solid var(--line);background:var(--surface);border-radius:8px;padding:6px 12px}
55
+ .ghost:hover{border-color:var(--red);color:var(--red-hi)}
56
+ .suggest{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:18px}
57
+ .suggest button{border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:6px 14px;font-size:13px}
58
+ .suggest button:hover{border-color:var(--red);color:var(--red-hi)}
59
+
60
+ /* conversation */
61
+ .thread{max-width:820px;margin:0 auto;display:flex;flex-direction:column;gap:14px;padding-bottom:16px}
62
+ .msg{max-width:100%;overflow-wrap:anywhere;white-space:pre-wrap}
63
+ .msg.user{align-self:flex-end;background:var(--red);color:#fff;border-radius:18px 18px 4px 18px;padding:9px 14px;max-width:80%}
64
+ .msg.bot{align-self:flex-start;display:flex;gap:10px}
65
+ .msg.bot .av{width:26px;height:26px;border-radius:8px;background:var(--red);color:#fff;font-weight:800;font-size:13px;display:grid;place-items:center;flex:none;margin-top:2px}
66
+ .msg.bot .txt{padding-top:2px}
67
+ .msg.thinking .txt{color:var(--muted)}
68
+ .msg.thinking button{margin-left:8px;border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:1px 10px;font-size:12px}
69
+ .pills{display:flex;gap:4px;flex-wrap:wrap;margin-top:6px}
70
+ .pill{font-size:11px;border-radius:999px;padding:1px 9px;background:var(--red-tint);color:var(--red-hi)}
71
+ .attached{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px;justify-content:flex-end}
72
+
73
+ /* one question at a time */
74
+ .qcard{align-self:stretch;border:1px solid var(--red);border-radius:14px;padding:14px 16px;background:var(--surface);box-shadow:0 2px 14px rgba(230,26,39,.08)}
75
+ .qhead{font-size:12px;color:var(--red-hi);font-weight:600;letter-spacing:.3px;text-transform:uppercase}
76
+ .qtitle{font-size:17px;font-weight:700;margin:2px 0 2px}
77
+ .qhelp{color:var(--muted);font-size:13px;margin:0 0 10px}
78
+ .qbody label{display:block;margin:6px 0}
79
+ .qbody label.item{display:flex;margin:2px 0}
80
+ .qbody input[type=text],.qbody input[type=password],.qbody select,.qbody textarea{width:100%;border:1px solid var(--line);border-radius:8px;padding:7px 10px;background:var(--surface);margin-top:2px}
81
+ .qbody input:focus,.qbody select:focus,.qbody textarea:focus{border-color:var(--red);outline:none;box-shadow:0 0 0 3px rgba(230,26,39,.12)}
82
+ .qbody h4{margin:12px 0 4px;font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.3px}
83
+ .item{display:flex;gap:10px;align-items:flex-start;padding:7px 8px;border:1px solid transparent;border-radius:10px}
84
+ .item:hover{background:var(--red-soft)}
85
+ .item input{accent-color:var(--red);margin-top:4px}
86
+ .item .why{color:var(--muted);font-size:12px}
87
+ .item.risky{background:var(--red-soft);border-color:var(--line)}
88
+ .item.locked,.item.off{opacity:.6}
89
+ .badge{font-size:11px;border-radius:999px;padding:0 8px;border:1px solid var(--red);color:var(--red-hi);white-space:nowrap}
90
+ .choice{display:flex;gap:8px;flex-wrap:wrap;margin:4px 0}
91
+ .choice label{display:flex;gap:8px;align-items:center;border:1px solid var(--line);border-radius:10px;padding:8px 12px;margin:0;cursor:pointer}
92
+ .choice label:has(input:checked){border-color:var(--red);background:var(--red-tint)}
93
+ .choice input{accent-color:var(--red)}
94
+ .steprow{display:grid;grid-template-columns:130px 1fr auto;gap:6px;margin:5px 0;align-items:center}
95
+ .steprow button{border:1px solid var(--line);background:var(--surface);border-radius:8px;padding:4px 8px}
96
+ .btnrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:12px}
97
+ .btn{border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:7px 16px;font-weight:500}
98
+ .btn:hover:not(:disabled){border-color:var(--red);color:var(--red-hi)}
99
+ .btn.primary{background:var(--red);border-color:var(--red);color:#fff;font-weight:600}
100
+ .btn.primary:hover:not(:disabled){background:var(--red-dark);color:#fff}
101
+ .reflist{display:flex;gap:6px;flex-wrap:wrap;margin:6px 0}
102
+ .refitem{background:var(--red-tint);border-radius:999px;padding:2px 4px 2px 12px;font-size:12px;color:var(--red-hi)}
103
+ .refitem button{border:0;background:none;padding:0 6px;color:var(--red-hi)}
104
+ .notes{background:var(--red-soft);border:1px solid var(--line);border-radius:10px;padding:8px 12px;font-size:13px}
105
+ .notes ul{margin:4px 0 0 18px;padding:0}
106
+ .answered{align-self:stretch;display:flex;gap:10px;align-items:baseline;border-left:3px solid var(--red);padding:2px 0 2px 12px;font-size:14px}
107
+ .answered .k{font-weight:600}.answered .v{color:var(--ink);overflow-wrap:anywhere}
108
+ .answered button{margin-left:auto;border:0;background:none;color:var(--red-hi);font-size:12px;text-decoration:underline;flex:none}
109
+ .summary{width:100%;border-collapse:collapse;font-size:14px}
110
+ .summary td{padding:5px 8px;border-bottom:1px solid var(--line);vertical-align:top}
111
+ .summary td:first-child{color:var(--muted);width:130px}
112
+
113
+ /* the build */
114
+ .run{align-self:stretch;border:1px solid var(--line);border-radius:14px;padding:14px 16px}
115
+ .runstatus{font-weight:700;margin-bottom:6px}
116
+ .tabs{display:flex;gap:6px;margin-bottom:8px;flex-wrap:wrap}
117
+ .tabs button{border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:4px 14px}
118
+ .tabs button.active{background:var(--red);border-color:var(--red);color:#fff}
119
+ .counters{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-bottom:8px}
120
+ .counters b{color:var(--ink)}.counters .bad{color:var(--red-hi)}
121
+ .events{background:var(--red-soft);border:1px solid var(--line);border-radius:10px;padding:8px 10px;max-height:34vh;overflow:auto;font-size:13px}
122
+ .ev{padding:2px 0;overflow-wrap:anywhere}.ev .t{color:var(--muted);font-size:11px;margin-right:6px}
123
+ .ev-step_start{font-weight:700;margin-top:6px}.ev-model_call{color:var(--muted)}.ev-file{color:var(--red-hi)}
124
+ .ev-blocked,.ev-error{color:var(--red-hi);font-weight:600}.ev-check,.ev-warning,.ev-cancelled{color:var(--red-hi)}
125
+ .run h3{font-size:14px;margin:12px 0 6px}
126
+ .filesrow{display:grid;grid-template-columns:minmax(120px,220px) 1fr;gap:10px}
127
+ .files{list-style:none;margin:0;padding:0}
128
+ .files button{width:100%;text-align:left;border:0;border-bottom:1px solid var(--line);background:none;padding:6px 8px;font-size:13px}
129
+ .files button.active{background:var(--red-tint);color:var(--red-hi)}
130
+ .preview{margin:0;max-height:40vh;overflow:auto;background:var(--red-soft);border:1px solid var(--line);border-radius:10px;padding:10px;font:12px/1.45 ui-monospace,Menlo,Consolas,monospace;white-space:pre}
131
+ .linkbtn{display:inline-block;border:1px solid var(--red);color:var(--red-hi);border-radius:999px;padding:6px 16px;text-decoration:none;margin-top:10px;font-weight:600}
132
+ .linkbtn:hover{background:var(--red);color:#fff}
133
+ .headline{font-size:17px;font-weight:700;margin:6px 0 10px}
134
+ table.cmp{border-collapse:collapse;width:100%;font-size:13px}
135
+ .cmp th,.cmp td{border-bottom:1px solid var(--line);padding:6px 8px;text-align:right}
136
+ .cmp th:first-child,.cmp td:first-child{text-align:left}
137
+ .cmp tr.saved td{font-weight:700;background:var(--red-tint)}
138
+ .cmp td.neg{color:var(--muted)}
139
+
140
+ /* composer */
141
+ .composer{max-width:820px;width:calc(100% - 32px);margin:0 auto 14px;border:1px solid var(--line);border-radius:22px;padding:10px 12px 8px;background:var(--surface);box-shadow:0 4px 22px rgba(0,0,0,.6)}
142
+ .composer:focus-within{border-color:var(--red);box-shadow:0 4px 22px rgba(230,26,39,.14)}
143
+ .composer textarea{width:100%;border:0;outline:none;resize:none;padding:4px 6px;background:none;max-height:160px}
144
+ .bar{display:flex;align-items:center;gap:8px;margin-top:4px}
145
+ .modelpick select{border:1px solid var(--line);border-radius:999px;padding:5px 12px;background:var(--surface);font-size:13px;max-width:240px}
146
+ .modelpick select:hover:not(:disabled){border-color:var(--red)}
147
+ .sendbtn{width:36px;height:36px;border-radius:50%;border:0;background:var(--red);color:#fff;display:grid;place-items:center}
148
+ .sendbtn:hover:not(:disabled){background:var(--red-dark)}
149
+ .refchips{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:4px}
150
+
151
+ @media (max-width:860px){
152
+
153
+ .top{display:flex}
154
+ .side{position:fixed;z-index:5;inset:0 auto 0 0;transform:translateX(-100%);transition:transform .15s}
155
+ .side.open{transform:none;box-shadow:0 0 30px rgba(0,0,0,.8)}
156
+ .panelcol.right{margin-left:0}
157
+ .filesrow{grid-template-columns:1fr}
158
+ .steprow{grid-template-columns:1fr}
159
+ }
160
+ @media (prefers-reduced-motion:reduce){.iconbtn.live{animation:none}.side{transition:none}}
161
+
162
+ /* the Claude look: calm, centred, little chrome; the colours stay black, red and white */
163
+ :root{--side:#0a0a0a;--card:#141414;--bubble:#262626}
164
+ .side{width:260px;background:var(--side);border-right:1px solid #1c1c1c;padding:12px 8px}
165
+ .brand{padding:4px 10px 14px}
166
+ .mark{width:auto;height:auto;background:none;color:var(--red);font-size:22px;font-weight:400;border-radius:0}
167
+ .brandname{font-size:18px;font-weight:600;letter-spacing:-.2px}
168
+ .navitem{border-radius:10px;padding:8px 10px;color:#e6e6e6}
169
+ .navitem.active{background:transparent;color:var(--ink);font-weight:500}
170
+ .navitem.active .ico{background:var(--red);color:#fff;border-radius:50%;width:22px;height:22px;display:grid;place-items:center;font-size:16px;line-height:1}
171
+ .navitem:hover,.runitem:hover{background:#1a1a1a}
172
+ .navhead{margin:20px 10px 6px;font-size:12px;color:var(--muted)}
173
+ .chip{border-radius:10px;font-size:12px}
174
+
175
+ .main{padding:28px 20px 8px}
176
+ .empty{margin:0 auto;text-align:center;max-width:720px}
177
+ .empty .spark{color:var(--red);font-size:34px;line-height:1;margin-bottom:10px}
178
+ .empty h1{font-size:36px;font-weight:500;letter-spacing:-.8px;margin:0}
179
+ .mainwrap.is-empty{justify-content:center}
180
+ .mainwrap.is-empty .main{flex:0 0 auto;overflow:visible;padding:0 20px 18px}
181
+ .mainwrap.is-empty .composer{margin-bottom:0}
182
+ .below{max-width:820px;width:calc(100% - 32px);margin:14px auto 0;text-align:center}
183
+ .below[hidden]{display:none}
184
+ .suggest{margin-top:0}
185
+ .suggest button{background:transparent;border-color:#333;color:#d4d4d4;padding:7px 14px}
186
+ .suggest button:hover{background:#1a1a1a}
187
+ .linklike{border:0;background:none;color:var(--muted);font-size:13px;margin-top:12px;text-decoration:underline;padding:2px 4px}
188
+ .linklike:hover{color:var(--ink)}
189
+ .mainwrap:not(.is-empty) .below{display:none}
190
+
191
+ .composer{border-radius:24px;background:var(--card);border-color:#2c2c2c;padding:12px 14px 8px;box-shadow:0 2px 24px rgba(0,0,0,.5)}
192
+ .composer:focus-within{border-color:#555;box-shadow:0 2px 24px rgba(229,9,20,.12)}
193
+ .composer textarea{font-size:16px;padding:6px 4px;min-height:28px}
194
+ .modelpick select{border:0;background:transparent;color:var(--muted);padding:6px 8px;border-radius:10px;font-size:13px;max-width:200px}
195
+ .modelpick select:hover:not(:disabled){background:#222;color:var(--ink)}
196
+ .iconbtn{border-color:transparent;background:transparent;color:var(--muted)}
197
+ .iconbtn:hover:not(:disabled){background:#222;border-color:transparent;color:var(--ink)}
198
+ .iconbtn.live{background:var(--red);color:#fff}
199
+ .sendbtn{border-radius:10px}
200
+
201
+ .thread{max-width:760px;gap:22px}
202
+ .msg.user{align-self:flex-start;background:var(--bubble);color:var(--ink);border-radius:16px;padding:10px 16px;max-width:85%}
203
+ .msg.bot{gap:12px}
204
+ .msg.bot .av{background:none;color:var(--red);width:22px;height:22px;font-size:20px;font-weight:400;margin-top:0;border-radius:0}
205
+ .msg.bot .txt{padding-top:0;line-height:1.65}
206
+
207
+ .qcard{border:1px solid #2c2c2c;border-radius:18px;background:var(--card);padding:18px 20px;box-shadow:none}
208
+ .qhead{color:var(--muted);font-weight:500;letter-spacing:.4px}
209
+ .qtitle{font-size:18px;font-weight:600}
210
+ .item{border-radius:12px}
211
+ .item.risky{background:#1a1111;border-color:#3a1c1f}
212
+ .btn{border-color:#333}
213
+ .btn.primary{border-radius:10px}
214
+ .btn{border-radius:10px}
215
+ .answered{border-left:0;padding:2px 0;color:var(--muted)}
216
+ .answered .k{color:var(--ink);font-weight:500}.answered .k::after{content:":"}
217
+ .answered .v{color:#d4d4d4}
218
+ .run{border:1px solid #2c2c2c;border-radius:18px;background:var(--card)}
219
+ .events,.preview{background:#0d0d0d;border-color:#262626}
220
+ @media (max-width:860px){.empty h1{font-size:28px}}
221
+
222
+ /* ---- Chat / Editor switch ---- */
223
+ .top{display:flex;justify-content:center;border-bottom:0;padding:10px 12px 0}
224
+ .top .menu,.top .toptitle{display:none}
225
+ .views{display:inline-flex;gap:2px;background:#161616;border:1px solid #2a2a2a;border-radius:10px;padding:3px}
226
+ .views button{border:0;background:transparent;color:var(--muted);padding:6px 16px;border-radius:8px;font-size:13px;font-weight:500}
227
+ .views button.active{background:#2a2a2a;color:var(--ink)}
228
+ .views button:disabled{opacity:.4;cursor:not-allowed}
229
+ @media (max-width:860px){.top{justify-content:space-between}.top .menu{display:inline-flex}}
230
+
231
+ /* ---- The editor: files | code | Ask Pal ---- */
232
+ .editor{flex:1;min-width:0;display:grid;grid-template-columns:220px minmax(0,1fr) 360px;height:100%;background:#0d0d0d}
233
+ .editor[hidden],.mainwrap[hidden]{display:none}
234
+ .ed-h{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;padding:14px 14px 8px}
235
+ .ed-files{border-right:1px solid #1c1c1c;display:flex;flex-direction:column;min-height:0;padding-bottom:12px;background:var(--side)}
236
+ .edfiles{list-style:none;margin:0;padding:0 6px;overflow:auto;flex:1}
237
+ .edfiles button{display:flex;justify-content:space-between;gap:6px;width:100%;text-align:left;border:0;background:transparent;color:#d4d4d4;padding:6px 8px;border-radius:8px;font:13px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
238
+ .edfiles button:hover{background:#1a1a1a}
239
+ .edfiles button.active{background:#262626;color:#fff}
240
+ .fname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
241
+ .dotmark{color:var(--red-hi);font-size:10px}
242
+ .ednew{display:flex;gap:4px;padding:8px 10px 0}
243
+ .ednew input{flex:1;min-width:0;background:#141414;border:1px solid #2a2a2a;border-radius:8px;color:var(--ink);padding:6px 8px;font-size:12px}
244
+ .ed-files .linkbtn{margin:10px 10px 0;text-align:center;font-size:12px;padding:5px 10px}
245
+ .ed-center{display:flex;flex-direction:column;min-width:0;min-height:0;border-right:1px solid #1c1c1c}
246
+ .ed-tabs{display:flex;overflow-x:auto;background:#101010;border-bottom:1px solid #1c1c1c;min-height:38px}
247
+ .edtab{display:flex;align-items:center;border-right:1px solid #1c1c1c;color:var(--muted)}
248
+ .edtab.active{background:#0d0d0d;color:var(--ink);box-shadow:inset 0 -2px 0 var(--red)}
249
+ .edtab button{border:0;background:transparent;color:inherit;font-size:13px;padding:9px 6px 9px 12px}
250
+ .edtab .edtabx{padding:9px 10px 9px 4px;font-size:16px;line-height:1}
251
+ .edtab .edtabx:hover{color:var(--red-hi)}
252
+ .ed-pane{position:relative;flex:1;min-height:0;display:flex;overflow:hidden}
253
+ .edempty{margin:auto;color:var(--muted)}
254
+ .gutter,.code{margin:0;padding:12px 0;font:13px/20px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;tab-size:2}
255
+ .gutter{width:52px;flex:none;overflow:hidden;text-align:right;padding-right:10px;color:#555;background:#0d0d0d;user-select:none;border-right:1px solid #1a1a1a}
256
+ .code{flex:1;min-width:0;border:0;outline:0;resize:none;background:#0d0d0d;color:#e8e8e8;padding-left:14px;overflow:auto;white-space:pre;caret-color:var(--red-hi)}
257
+ .code:read-only{color:#bbb}
258
+ .code[hidden],.gutter[hidden],.edempty[hidden],.ed-diff[hidden]{display:none}
259
+ .ed-diff{flex:1;overflow:auto;padding:0 0 20px}
260
+ .dbar{position:sticky;top:0;display:flex;align-items:center;gap:8px;padding:10px 14px;background:#161616;border-bottom:1px solid #2a2a2a;font-size:13px}
261
+ .dfile{margin:14px;border:1px solid #2a2a2a;border-radius:12px;overflow:hidden}
262
+ .dhead{padding:8px 12px;background:#161616;font-size:13px;border-bottom:1px solid #2a2a2a}
263
+ .dlines{margin:0;padding:6px 0;font:12.5px/19px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow-x:auto}
264
+ .dl{display:block;padding:0 12px;white-space:pre}
265
+ .d-add{background:rgba(46,160,67,.18);color:#b9f0c4}
266
+ .d-del{background:rgba(229,9,20,.18);color:#ffb3b8}
267
+ .d-hunk{color:#777;background:#141414}
268
+ .d-ctx{color:#a8a8a8}
269
+ .ed-bar{display:flex;align-items:center;gap:12px;padding:6px 12px;border-top:1px solid #1c1c1c;background:#101010;font-size:12px;color:var(--muted)}
270
+ .edpath{font-family:ui-monospace,Menlo,Consolas,monospace;color:#cfcfcf;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
271
+ .edstatus.bad{color:var(--red-hi)}
272
+ .ed-bar .btn{padding:4px 14px}
273
+ .ed-ask{display:flex;flex-direction:column;min-height:0;background:var(--side)}
274
+ .ed-ask .ed-h{text-transform:none;font-size:14px;color:var(--ink);font-weight:600}
275
+ .ed-ask .mark{font-size:16px}
276
+ .edmsgs{flex:1;overflow:auto;padding:4px 14px 10px;display:flex;flex-direction:column;gap:10px}
277
+ .edmsg{font-size:14px;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere;color:#e2e2e2}
278
+ .edmsg.me{align-self:flex-end;background:var(--bubble);border-radius:14px;padding:8px 12px;max-width:92%}
279
+ .edmsg.meta{font-size:12px;color:var(--muted)}
280
+ .edmsg.wait{color:var(--muted);font-style:italic}
281
+ .edmsg.ok{color:#8fe3a1}
282
+ .edmsg.bad{color:var(--red-hi)}
283
+ .edmeter{margin:0;padding:8px 14px;font-size:12px;line-height:1.5;color:var(--muted);border-top:1px solid #1c1c1c}
284
+ .edmeter b{color:var(--ink)}
285
+ .edform{margin:0 12px 12px;border:1px solid #2c2c2c;border-radius:16px;background:var(--card);padding:8px 10px}
286
+ .edform:focus-within{border-color:#555}
287
+ .edform textarea{width:100%;box-sizing:border-box;background:transparent;border:0;outline:0;resize:none;color:var(--ink);font:14px/1.5 inherit}
288
+ .edform .bar{display:flex;align-items:center}
289
+ @media (max-width:1100px){.editor{grid-template-columns:180px minmax(0,1fr) 300px}}
290
+ @media (max-width:860px){.editor{grid-template-columns:1fr;grid-template-rows:auto minmax(320px,1fr) 320px;height:auto;overflow:auto}.ed-files{max-height:160px}}
291
+
292
+ .ed-ask .ed-h{display:flex;align-items:center;gap:8px}
293
+ /* the Chat / Editor switch stays a small pill at the top, whatever the empty-state centring does */
294
+ .mainwrap{position:relative}
295
+ .top{position:absolute;top:0;left:0;right:0;z-index:2;justify-content:center;pointer-events:none}
296
+ .top>*{pointer-events:auto}
297
+ .top .views{flex:0 0 auto;width:auto}
298
+ .main{padding-top:56px}
299
+ .mainwrap.is-empty .main{padding-top:0}
300
+ @media (max-width:860px){.top{position:static;pointer-events:auto}.main{padding-top:12px}}
301
+
302
+ /* the Pal logo: sidebar, start screen, replies, Ask Pal */
303
+ img.mark{width:28px;height:28px;object-fit:contain;background:none;border-radius:0;display:block}
304
+ .ed-ask img.mark{width:20px;height:20px}
305
+ .empty img.spark{width:72px;height:72px;object-fit:contain;display:block;margin:0 auto 14px}
306
+ .msg.bot img.av{width:24px;height:24px;object-fit:contain;background:none;border-radius:0;flex:none;margin-top:0}