dsh-biocore 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/README.md +11 -0
  2. package/lib/core-worker.js +268 -0
  3. package/lib/index.js +160 -70
  4. package/lib/modules/autonomy.js +125 -0
  5. package/lib/modules/cache-stats.js +48 -0
  6. package/lib/modules/core-turn.js +24 -6
  7. package/lib/modules/expression-inject.js +0 -10
  8. package/lib/modules/expression-refresh.js +0 -9
  9. package/lib/modules/memory-capture.js +2 -1
  10. package/lib/modules/memory-inject.js +50 -5
  11. package/lib/modules/memory-tools.js +7 -4
  12. package/lib/modules/python-env.js +46 -0
  13. package/lib/modules/safety-gate.js +0 -3
  14. package/lib/modules/series.js +54 -0
  15. package/lib/modules/switch.js +16 -0
  16. package/lib/py-bridge.js +81 -15
  17. package/package.json +1 -1
  18. package/python/biocore_memory/core/config.py +138 -127
  19. package/python/biocore_memory/engine.py +2653 -2476
  20. package/python/biocore_memory/recall/embedding.py +129 -0
  21. package/python/biocore_memory/recall/feedback.py +202 -0
  22. package/python/biocore_model/preference_drift.py +255 -0
  23. package/python/biocore_model/tests/__init__.py +1 -0
  24. package/python/biocore_model/tests/core_mode_ui_check.mjs +63 -0
  25. package/python/biocore_model/tests/core_status_check.mjs +29 -0
  26. package/python/biocore_model/tests/dom_safe_check.mjs +22 -0
  27. package/python/biocore_model/tests/leak_samples_run.py +18 -0
  28. package/python/biocore_model/tests/orb_ring_check.mjs +20 -0
  29. package/python/biocore_model/tests/panel_html_check.mjs +63 -0
  30. package/python/biocore_model/tests/persona_flow_check.mjs +17 -0
  31. package/python/biocore_model/tests/render_guard_check.mjs +19 -0
  32. package/python/biocore_model/tests/switch_groups_check.mjs +94 -0
  33. package/python/biocore_model/tests/tabs_state_check.mjs +24 -0
  34. package/python/biocore_model/tests/test_affective_labor.py +102 -0
  35. package/python/biocore_model/tests/test_appraisal.py +137 -0
  36. package/python/biocore_model/tests/test_appraisal_action.py +55 -0
  37. package/python/biocore_model/tests/test_arch_convergence.py +35 -0
  38. package/python/biocore_model/tests/test_attachment_behavior.py +95 -0
  39. package/python/biocore_model/tests/test_attachment_regulation.py +63 -0
  40. package/python/biocore_model/tests/test_attachment_state.py +29 -0
  41. package/python/biocore_model/tests/test_attribution.py +56 -0
  42. package/python/biocore_model/tests/test_attributor.py +108 -0
  43. package/python/biocore_model/tests/test_autonomic.py +69 -0
  44. package/python/biocore_model/tests/test_autonomy_accumulator.py +84 -0
  45. package/python/biocore_model/tests/test_autonomy_affect.py +62 -0
  46. package/python/biocore_model/tests/test_autonomy_blame.py +44 -0
  47. package/python/biocore_model/tests/test_autonomy_caps.py +29 -0
  48. package/python/biocore_model/tests/test_autonomy_check.py +40 -0
  49. package/python/biocore_model/tests/test_autonomy_clingy.py +41 -0
  50. package/python/biocore_model/tests/test_autonomy_cooldown_selfcontact.py +138 -0
  51. package/python/biocore_model/tests/test_autonomy_frustration.py +42 -0
  52. package/python/biocore_model/tests/test_autonomy_hourly_limit.py +46 -0
  53. package/python/biocore_model/tests/test_autonomy_loop.py +64 -0
  54. package/python/biocore_model/tests/test_autonomy_mode.py +37 -0
  55. package/python/biocore_model/tests/test_autonomy_model.py +60 -0
  56. package/python/biocore_model/tests/test_autonomy_model_v2.py +68 -0
  57. package/python/biocore_model/tests/test_autonomy_module_text.py +104 -0
  58. package/python/biocore_model/tests/test_autonomy_params.py +163 -0
  59. package/python/biocore_model/tests/test_autonomy_reason.py +34 -0
  60. package/python/biocore_model/tests/test_autonomy_self.py +153 -0
  61. package/python/biocore_model/tests/test_autonomy_send_gate.py +38 -0
  62. package/python/biocore_model/tests/test_autonomy_silence.py +37 -0
  63. package/python/biocore_model/tests/test_autonomy_status.py +35 -0
  64. package/python/biocore_model/tests/test_autonomy_test_trigger.py +24 -0
  65. package/python/biocore_model/tests/test_autonomy_tick.py +148 -0
  66. package/python/biocore_model/tests/test_autonomy_v4.py +64 -0
  67. package/python/biocore_model/tests/test_autonomy_v5.py +43 -0
  68. package/python/biocore_model/tests/test_autonomy_v7.py +48 -0
  69. package/python/biocore_model/tests/test_autonomy_v_theta.py +85 -0
  70. package/python/biocore_model/tests/test_batch1_wiring.py +231 -0
  71. package/python/biocore_model/tests/test_batch2_wiring.py +231 -0
  72. package/python/biocore_model/tests/test_batch3_wiring.py +223 -0
  73. package/python/biocore_model/tests/test_bio_tick.py +202 -0
  74. package/python/biocore_model/tests/test_boundary.py +183 -0
  75. package/python/biocore_model/tests/test_boundary_gate.py +295 -0
  76. package/python/biocore_model/tests/test_brain_split.py +99 -0
  77. package/python/biocore_model/tests/test_co_recall.py +350 -0
  78. package/python/biocore_model/tests/test_commitment_extractor.py +197 -0
  79. package/python/biocore_model/tests/test_compassion_fatigue.py +84 -0
  80. package/python/biocore_model/tests/test_connection_bids.py +69 -0
  81. package/python/biocore_model/tests/test_core_bridge.py +88 -0
  82. package/python/biocore_model/tests/test_core_bridge_episode.py +14 -0
  83. package/python/biocore_model/tests/test_core_bridge_forget.py +17 -0
  84. package/python/biocore_model/tests/test_core_bridge_identity.py +15 -0
  85. package/python/biocore_model/tests/test_core_bridge_media.py +17 -0
  86. package/python/biocore_model/tests/test_core_bridge_relation.py +17 -0
  87. package/python/biocore_model/tests/test_core_bridge_summary.py +17 -0
  88. package/python/biocore_model/tests/test_core_client.py +156 -0
  89. package/python/biocore_model/tests/test_core_commands.py +146 -0
  90. package/python/biocore_model/tests/test_core_mode.py +161 -0
  91. package/python/biocore_model/tests/test_core_state.py +240 -0
  92. package/python/biocore_model/tests/test_criticality.py +61 -0
  93. package/python/biocore_model/tests/test_cross_session_copy.py +67 -0
  94. package/python/biocore_model/tests/test_debug_values.py +169 -0
  95. package/python/biocore_model/tests/test_defense_mechanisms.py +177 -0
  96. package/python/biocore_model/tests/test_delta_budget.py +157 -0
  97. package/python/biocore_model/tests/test_diag_trace.py +201 -0
  98. package/python/biocore_model/tests/test_directives_compat.py +698 -0
  99. package/python/biocore_model/tests/test_dissonance.py +97 -0
  100. package/python/biocore_model/tests/test_drift_sign.py +87 -0
  101. package/python/biocore_model/tests/test_embedding_fallback.py +277 -0
  102. package/python/biocore_model/tests/test_embedding_local.py +279 -0
  103. package/python/biocore_model/tests/test_embedding_mode.py +175 -0
  104. package/python/biocore_model/tests/test_embedding_modes.py +342 -0
  105. package/python/biocore_model/tests/test_emotion_geometry.py +114 -0
  106. package/python/biocore_model/tests/test_emotion_probe.py +214 -0
  107. package/python/biocore_model/tests/test_emotion_probe_concurrency.py +128 -0
  108. package/python/biocore_model/tests/test_entity_graph.py +198 -0
  109. package/python/biocore_model/tests/test_entity_resolve.py +446 -0
  110. package/python/biocore_model/tests/test_envy.py +173 -0
  111. package/python/biocore_model/tests/test_exit_or_silence.py +209 -0
  112. package/python/biocore_model/tests/test_expr_guard.py +1 -0
  113. package/python/biocore_model/tests/test_expr_intent.py +66 -0
  114. package/python/biocore_model/tests/test_expr_state.py +66 -0
  115. package/python/biocore_model/tests/test_expr_template.py +71 -0
  116. package/python/biocore_model/tests/test_expr_tone.py +41 -0
  117. package/python/biocore_model/tests/test_extreme_scenarios.py +147 -0
  118. package/python/biocore_model/tests/test_feedback_flow.py +185 -0
  119. package/python/biocore_model/tests/test_feedback_guard.py +65 -0
  120. package/python/biocore_model/tests/test_feedback_llm.py +59 -0
  121. package/python/biocore_model/tests/test_feedback_llm_inferred.py +140 -0
  122. package/python/biocore_model/tests/test_feedback_memory.py +63 -0
  123. package/python/biocore_model/tests/test_feedback_user.py +61 -0
  124. package/python/biocore_model/tests/test_frustration_curve.py +66 -0
  125. package/python/biocore_model/tests/test_global_bio_state.py +116 -0
  126. package/python/biocore_model/tests/test_governance.py +181 -0
  127. package/python/biocore_model/tests/test_granularity.py +133 -0
  128. package/python/biocore_model/tests/test_graph_extract.py +224 -0
  129. package/python/biocore_model/tests/test_graph_recall.py +226 -0
  130. package/python/biocore_model/tests/test_graph_sqlite.py +298 -0
  131. package/python/biocore_model/tests/test_growth.py +301 -0
  132. package/python/biocore_model/tests/test_intent_render.py +60 -0
  133. package/python/biocore_model/tests/test_intero_regulation.py +224 -0
  134. package/python/biocore_model/tests/test_intero_style.py +146 -0
  135. package/python/biocore_model/tests/test_item3_numeric.py +105 -0
  136. package/python/biocore_model/tests/test_item6_numeric.py +116 -0
  137. package/python/biocore_model/tests/test_layered_memory.py +174 -0
  138. package/python/biocore_model/tests/test_leak_guard.py +75 -0
  139. package/python/biocore_model/tests/test_learning_probe.py +93 -0
  140. package/python/biocore_model/tests/test_life_loop.py +222 -0
  141. package/python/biocore_model/tests/test_life_loop_10s.py +131 -0
  142. package/python/biocore_model/tests/test_local_embedding_health.py +258 -0
  143. package/python/biocore_model/tests/test_memory_affect_encoding.py +79 -0
  144. package/python/biocore_model/tests/test_memory_backend.py +332 -0
  145. package/python/biocore_model/tests/test_memory_dedup.py +316 -0
  146. package/python/biocore_model/tests/test_memory_dual.py +219 -0
  147. package/python/biocore_model/tests/test_memory_dual_wiring.py +219 -0
  148. package/python/biocore_model/tests/test_memory_feedback.py +241 -0
  149. package/python/biocore_model/tests/test_memory_fixes.py +84 -0
  150. package/python/biocore_model/tests/test_memory_forgetting.py +58 -0
  151. package/python/biocore_model/tests/test_memory_inject.py +211 -0
  152. package/python/biocore_model/tests/test_memory_mood_recall.py +118 -0
  153. package/python/biocore_model/tests/test_memory_store.py +372 -0
  154. package/python/biocore_model/tests/test_metacog.py +103 -0
  155. package/python/biocore_model/tests/test_migrate.py +245 -0
  156. package/python/biocore_model/tests/test_migrate_store.py +194 -0
  157. package/python/biocore_model/tests/test_mind_wander.py +65 -0
  158. package/python/biocore_model/tests/test_mood.py +35 -0
  159. package/python/biocore_model/tests/test_narrative.py +114 -0
  160. package/python/biocore_model/tests/test_needs_esteem.py +51 -0
  161. package/python/biocore_model/tests/test_needs_events.py +205 -0
  162. package/python/biocore_model/tests/test_needs_sleep.py +54 -0
  163. package/python/biocore_model/tests/test_noise_bank.py +54 -0
  164. package/python/biocore_model/tests/test_numeric_schema.py +98 -0
  165. package/python/biocore_model/tests/test_output_protocol.py +65 -0
  166. package/python/biocore_model/tests/test_page_debug.py +147 -0
  167. package/python/biocore_model/tests/test_page_status_autonomy.py +215 -0
  168. package/python/biocore_model/tests/test_pipeline.py +345 -0
  169. package/python/biocore_model/tests/test_pipeline_api.py +192 -0
  170. package/python/biocore_model/tests/test_pipeline_mode.py +222 -0
  171. package/python/biocore_model/tests/test_plugin_config.py +85 -0
  172. package/python/biocore_model/tests/test_policy_learning.py +116 -0
  173. package/python/biocore_model/tests/test_possible_selves.py +88 -0
  174. package/python/biocore_model/tests/test_predictor.py +227 -0
  175. package/python/biocore_model/tests/test_preference_drift.py +142 -0
  176. package/python/biocore_model/tests/test_preset.py +142 -0
  177. package/python/biocore_model/tests/test_proactive_context.py +70 -0
  178. package/python/biocore_model/tests/test_proactive_history.py +90 -0
  179. package/python/biocore_model/tests/test_proactive_memory.py +141 -0
  180. package/python/biocore_model/tests/test_proactive_send_record.py +88 -0
  181. package/python/biocore_model/tests/test_probe_contract.py +71 -0
  182. package/python/biocore_model/tests/test_prospective.py +154 -0
  183. package/python/biocore_model/tests/test_provider_fallback.py +89 -0
  184. package/python/biocore_model/tests/test_reconstruction.py +111 -0
  185. package/python/biocore_model/tests/test_regulation_strategies.py +228 -0
  186. package/python/biocore_model/tests/test_relation_stage.py +114 -0
  187. package/python/biocore_model/tests/test_relationship_stage.py +59 -0
  188. package/python/biocore_model/tests/test_release_140.py +55 -0
  189. package/python/biocore_model/tests/test_repair_after_boundary.py +249 -0
  190. package/python/biocore_model/tests/test_reply_limit.py +86 -0
  191. package/python/biocore_model/tests/test_reply_limit_persist.py +48 -0
  192. package/python/biocore_model/tests/test_reply_split.py +52 -0
  193. package/python/biocore_model/tests/test_reply_split_astrbot.py +66 -0
  194. package/python/biocore_model/tests/test_reply_split_inject.py +53 -0
  195. package/python/biocore_model/tests/test_rerank.py +229 -0
  196. package/python/biocore_model/tests/test_rollback.py +175 -0
  197. package/python/biocore_model/tests/test_runtime.py +175 -0
  198. package/python/biocore_model/tests/test_runtime_active.py +205 -0
  199. package/python/biocore_model/tests/test_runtime_pipeline.py +1583 -0
  200. package/python/biocore_model/tests/test_runtime_proactive.py +231 -0
  201. package/python/biocore_model/tests/test_scheduler.py +79 -0
  202. package/python/biocore_model/tests/test_secrecy.py +105 -0
  203. package/python/biocore_model/tests/test_self_esteem.py +45 -0
  204. package/python/biocore_model/tests/test_self_intent.py +347 -0
  205. package/python/biocore_model/tests/test_self_interest.py +183 -0
  206. package/python/biocore_model/tests/test_self_layer_wiring.py +198 -0
  207. package/python/biocore_model/tests/test_self_verification.py +113 -0
  208. package/python/biocore_model/tests/test_situation.py +142 -0
  209. package/python/biocore_model/tests/test_sleep_circadian.py +41 -0
  210. package/python/biocore_model/tests/test_social_pain.py +49 -0
  211. package/python/biocore_model/tests/test_social_repair.py +67 -0
  212. package/python/biocore_model/tests/test_social_theory.py +78 -0
  213. package/python/biocore_model/tests/test_source_monitoring.py +204 -0
  214. package/python/biocore_model/tests/test_speak_like_group.py +36 -0
  215. package/python/biocore_model/tests/test_stages.py +226 -0
  216. package/python/biocore_model/tests/test_state_tag.py +86 -0
  217. package/python/biocore_model/tests/test_template_expr.py +65 -0
  218. package/python/biocore_model/tests/test_text_inference.py +70 -0
  219. package/python/biocore_model/tests/test_theta_params.py +115 -0
  220. package/python/biocore_model/tests/test_topic_control.py +200 -0
  221. package/python/biocore_model/tests/test_turn_memory.py +105 -0
  222. package/python/biocore_model/tests/test_turn_memory_panel.py +174 -0
  223. package/python/biocore_model/tests/test_ui_settings.py +84 -0
  224. package/python/biocore_model/tests/test_ui_settings_authority.py +179 -0
  225. package/python/biocore_model/tests/test_user_appraisal_async.py +155 -0
  226. package/python/biocore_model/tests/test_user_classify.py +122 -0
  227. package/python/biocore_model/tests/test_value_order.py +117 -0
  228. package/python/biocore_model/tests/test_voice_bank.py +105 -0
  229. package/python/biocore_model/tests/test_waiting_sense.py +216 -0
  230. package/python/biocore_model/tests/test_x_directives.py +101 -0
  231. package/python/biocore_model/tests/ui_compat_check.mjs +22 -0
  232. package/python/biocore_model/tests/view_mode_check.mjs +17 -0
  233. package/python/biocore_runtime/autonomy.py +208 -0
  234. package/python/biocore_runtime/core_state.py +302 -0
  235. package/python/biocore_runtime/governance.py +495 -0
  236. package/python/biocore_runtime/growth.py +528 -0
  237. package/python/biocore_runtime/pipeline.py +850 -23
  238. package/python/biocore_runtime/relationship_state.py +214 -0
  239. package/python/biocore_runtime/self_layer.py +103 -0
  240. package/python/biocore_runtime/service.py +162 -0
  241. package/python/biocore_runtime/standby.py +472 -0
  242. package/ui/panel-layout.js +83 -39
  243. package/ui/panel.css +885 -743
  244. package/ui/panel.html +356 -296
  245. package/ui/panel.js +739 -865
package/ui/panel.css CHANGED
@@ -1,833 +1,975 @@
1
- /* BioCore instrument panel — FlClash mobile spec. | layout v27
2
- 1) tokens 2) base 3) topbar 4) cards 5) figures 6) lists 7) forms
3
- 8) switches 9) nav 10) edit mode 11) desktop.
4
- Rule: one component rule per selector, px values from docs/DSH-PANEL-FLCLASH-SPEC.md. */
1
+ /* BioCore instrument panel — neumorphic skin (v30).
2
+ *
3
+ * The single visual spec is docs/STYLE-NEUMORPHISM.md. Every surface is the
4
+ * same family as the page, separated only by the fixed dual light source:
5
+ * dark #b8bcc2 bottom-right, light #ffffff top-left.
6
+ *
7
+ * raised 8px 8px 16px / -8px -8px 16px
8
+ * inset inset 8px 8px 16px / inset -8px -8px 16px
9
+ * field inset 6px 6px 12px (focus: inset 2px 2px 4px)
10
+ *
11
+ * Type 12 / 14 / 20 / 28 / 32 · radius 12 / 16 / 24 · motion 300ms ease-in-out
12
+ * No gradients, no pure black or white surfaces, no transforms.
13
+ */
5
14
 
6
- /* ---------- 1. tokens ---------- */
7
15
  :root {
8
- --page: #f2f2f7;
9
- --card: #ffffff;
10
- --block: #f6f6f9;
11
- --tone: #e9e9ee;
12
- --line: rgba(0, 0, 0, 0.08);
13
- --line-strong: rgba(0, 0, 0, 0.14);
14
- --text: #1c1c1e;
15
- --text-2: #6c6c70;
16
- --text-3: #8e8e93;
17
- --accent: #2b83ff;
18
- --accent-soft: rgba(43, 131, 255, 0.14);
19
- --ok: #34c759;
20
- --warn: #ff9f0a;
21
- --danger: #d92b2b;
22
- --shadow-e1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 10px 24px -10px rgba(0, 0, 0, 0.14);
23
- --shadow-e2: 0 2px 6px rgba(0, 0, 0, 0.10), 0 24px 48px -14px rgba(0, 0, 0, 0.22);
24
-
25
- --pad-page: 16px;
26
- --pad-card: 18px;
27
- --gap-card: 12px;
28
- --gap-block: 10px;
29
- --radius-card: 28px;
30
- --radius-block: 18px;
31
- --radius-field: 14px;
32
- --radius-pill: 999px;
33
- --topbar-h: 64px;
34
- --nav-h: 64px;
16
+ color-scheme: light;
17
+ --bg: #e0e5ec;
18
+ --card: #f0f0f3;
19
+ --surface: #f0f0f3;
20
+ --shadow-dark: #b8bcc2;
21
+ --shadow-light: #ffffff;
22
+
23
+ --accent: #6d5dfc;
24
+ --accent-ink: #4f43d6;
25
+ --accent-ring: rgba(109, 93, 252, .35);
26
+ --ink: #333333;
27
+ --ink-2: #5e6774; /* spec #6b7280 measures 3.82:1 on the page; AA needs 4.5 */
28
+ --ink-3: #6b7280; /* spec value, kept for large or decorative text only */
29
+ --danger: #a12d2d;
30
+ --knob: #ffffff;
31
+ --orb-hi: rgba(255, 255, 255, .28);
32
+ --orb-lo: rgba(0, 0, 0, .18);
33
+
34
+ --fs-xs: 12px;
35
+ --fs-sm: 14px;
36
+ --fs-md: 20px;
37
+ --fs-lg: 28px;
38
+ --fs-xl: 32px;
39
+
40
+ --sp-1: 4px;
41
+ --sp-2: 8px;
42
+ --sp-3: 12px;
43
+ --sp-4: 16px;
44
+ --sp-6: 24px;
45
+ --sp-8: 32px;
46
+
47
+ --r-card: 24px;
48
+ --r-inner: 16px;
49
+ --r-chip: 12px;
50
+
51
+ --raise: 8px 8px 16px var(--shadow-dark), -8px -8px 16px var(--shadow-light);
52
+ --raise-sm: 4px 4px 8px var(--shadow-dark), -4px -4px 8px var(--shadow-light);
53
+ --raise-btn: 6px 6px 12px var(--shadow-dark), -6px -6px 12px var(--shadow-light);
54
+ --raise-hover: 4px 4px 8px var(--shadow-dark), -4px -4px 8px var(--shadow-light);
55
+ --sink: inset 8px 8px 16px var(--shadow-dark), inset -8px -8px 16px var(--shadow-light);
56
+ --sink-sm: inset 2px 2px 4px var(--shadow-dark), inset -2px -2px 4px var(--shadow-light);
57
+ --sink-deep: inset 6px 6px 12px var(--shadow-dark), inset -6px -6px 12px var(--shadow-light);
58
+
59
+ --t: 300ms ease-in-out;
60
+ --rail-w: 220px;
61
+ --rail-w-min: 64px;
62
+ --font: "Segoe UI Variable Text", "Segoe UI", -apple-system, BlinkMacSystemFont,
63
+ "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", sans-serif;
35
64
  }
65
+
66
+ /* ------------------------------------------------------------- 深色主题 ---
67
+ * One layout, two palettes. The light source never moves: top-left stays the
68
+ * bright side, bottom-right the dark side; only the two shadow values change.
69
+ * The host can pin a theme with <html data-theme="light|dark">, otherwise the
70
+ * OS preference decides. */
71
+ :root[data-theme="dark"] {
72
+ color-scheme: dark;
73
+ --bg: #2c2f36;
74
+ --card: #33373f;
75
+ --surface: #33373f;
76
+ --shadow-dark: #23262b;
77
+ --shadow-light: #3b4048;
78
+ --accent: #7c6bff;
79
+ --accent-ink: #a99cff;
80
+ --accent-ring: rgba(169, 156, 255, .4);
81
+ --ink: #e6e8ec;
82
+ --ink-2: #9aa0aa;
83
+ --ink-3: #9aa0aa;
84
+ --danger: #f19a9a;
85
+ --knob: #ffffff;
86
+ --orb-hi: rgba(255, 255, 255, .18);
87
+ --orb-lo: rgba(0, 0, 0, .32);
88
+ }
89
+
36
90
  @media (prefers-color-scheme: dark) {
37
- :root {
91
+ :root:not([data-theme="light"]) {
38
92
  color-scheme: dark;
39
- --page: #111113;
40
- --card: #1c1d1f;
41
- --block: #252628;
42
- --tone: #323234;
43
- --line: rgba(255, 255, 255, 0.08);
44
- --line-strong: rgba(255, 255, 255, 0.14);
45
- --text: #f5f5f7;
46
- --text-2: #a8a8ad;
47
- --text-3: #6f6f75;
48
- --shadow-e1: 0 1px 2px rgba(0, 0, 0, 0.50), 0 10px 28px -8px rgba(0, 0, 0, 0.55);
49
- --shadow-e2: 0 2px 6px rgba(0, 0, 0, 0.50), 0 32px 60px -14px rgba(0, 0, 0, 0.70);
93
+ --bg: #2c2f36;
94
+ --card: #33373f;
95
+ --surface: #33373f;
96
+ --shadow-dark: #23262b;
97
+ --shadow-light: #3b4048;
98
+ --accent: #7c6bff;
99
+ --accent-ink: #a99cff;
100
+ --accent-ring: rgba(169, 156, 255, .4);
101
+ --ink: #e6e8ec;
102
+ --ink-2: #9aa0aa;
103
+ --ink-3: #9aa0aa;
104
+ --danger: #f19a9a;
105
+ --knob: #ffffff;
106
+ --orb-hi: rgba(255, 255, 255, .18);
107
+ --orb-lo: rgba(0, 0, 0, .32);
50
108
  }
51
109
  }
52
- html[data-theme='light'] { color-scheme: light; }
53
- html[data-theme='dark'] {
54
- color-scheme: dark;
55
- --page: #111113; --card: #1c1d1f; --block: #252628; --tone: #323234;
56
- --line: rgba(255, 255, 255, 0.08); --line-strong: rgba(255, 255, 255, 0.14);
57
- --text: #f5f5f7; --text-2: #a8a8ad; --text-3: #6f6f75;
58
- --shadow-e1: 0 1px 2px rgba(0, 0, 0, 0.50), 0 10px 28px -8px rgba(0, 0, 0, 0.55);
59
- --shadow-e2: 0 2px 6px rgba(0, 0, 0, 0.50), 0 32px 60px -14px rgba(0, 0, 0, 0.70);
60
- }
61
110
 
62
- /* ---------- 2. base ---------- */
63
- *, *::before, *::after { box-sizing: border-box; }
111
+ * { box-sizing: border-box; }
64
112
  [hidden] { display: none !important; }
65
- html, body { min-height: 100%; }
113
+ html, body { height: 100%; }
66
114
  body {
67
115
  margin: 0;
68
- padding: calc(var(--topbar-h) + 24px) var(--pad-page) calc(var(--nav-h) + 28px + env(safe-area-inset-bottom, 0px));
69
- background: var(--page);
70
- color: var(--text);
71
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
72
- font-size: 15px;
73
- line-height: 20px;
74
- letter-spacing: -0.01em;
116
+ background: var(--bg);
117
+ color: var(--ink);
118
+ font-family: var(--font);
119
+ font-size: var(--fs-sm);
120
+ line-height: 22px;
75
121
  -webkit-font-smoothing: antialiased;
76
- -webkit-tap-highlight-color: transparent;
77
122
  }
78
- .panel { width: min(560px, 100%); margin: 0 auto; display: flex; flex-direction: column; gap: var(--gap-card); }
79
- .num, strong, .sub-value strong, .relation-value, .memory-stat strong, .triple-col strong { font-variant-numeric: tabular-nums; }
123
+ .sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
124
+ use { pointer-events: none; }
125
+ h1, h2, h3, p, dl, dd, dt, ul, li { margin: 0; }
126
+ button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
127
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
128
+
129
+ /* ---------------------------------------------------------------- shell --- */
130
+
131
+ body {
132
+ display: grid;
133
+ grid-template-columns: var(--rail-w) minmax(0, 1fr);
134
+ transition: grid-template-columns var(--t);
135
+ }
136
+ body.rail-collapsed { grid-template-columns: var(--rail-w-min) minmax(0, 1fr); }
137
+
138
+ .rail {
139
+ position: sticky;
140
+ top: 0;
141
+ align-self: start;
142
+ height: 100vh;
143
+ display: flex;
144
+ flex-direction: column;
145
+ gap: var(--sp-4);
146
+ margin: var(--sp-4) 0 var(--sp-4) var(--sp-4);
147
+ padding: var(--sp-4);
148
+ border-radius: var(--r-card);
149
+ background: var(--card);
150
+ box-shadow: var(--raise);
151
+ overflow: hidden;
152
+ }
153
+ .rail-top { display: flex; align-items: center; gap: var(--sp-2); min-height: 40px; }
154
+ .rail-mark {
155
+ flex: none; width: 36px; height: 36px; border-radius: var(--r-chip);
156
+ display: grid; place-items: center;
157
+ background: var(--card);
158
+ box-shadow: var(--raise-sm);
159
+ color: var(--accent);
160
+ }
161
+ .rail-mark svg { width: 18px; height: 18px; fill: currentColor; }
162
+ .rail-word { font-size: var(--fs-sm); font-weight: 700; letter-spacing: .01em; white-space: nowrap; }
163
+ .rail-toggle {
164
+ margin-left: auto; flex: none;
165
+ width: 32px; height: 32px; border-radius: var(--r-chip);
166
+ display: grid; place-items: center;
167
+ background: var(--card);
168
+ box-shadow: var(--raise-btn);
169
+ color: var(--ink-2);
170
+ transition: box-shadow var(--t), color var(--t);
171
+ }
172
+ .rail-toggle svg { width: 18px; height: 18px; }
173
+ .rail-toggle:hover { box-shadow: var(--raise-hover); }
174
+ .rail-toggle:active { box-shadow: var(--sink); }
175
+ body.rail-collapsed .rail-toggle svg { transform: none; }
176
+ body.rail-collapsed .rail-word,
177
+ body.rail-collapsed .rail-version,
178
+ body.rail-collapsed .rail-item span { display: none; }
179
+ body.rail-collapsed .rail-top { flex-direction: column; gap: var(--sp-2); }
180
+ body.rail-collapsed .rail-toggle { margin: 0; }
181
+ body.rail-collapsed .rail-item { justify-content: center; padding: 0; }
182
+
183
+ .rail-nav { display: flex; flex-direction: column; gap: var(--sp-2); }
184
+ .rail-item {
185
+ display: flex; align-items: center; gap: var(--sp-3);
186
+ height: 44px; padding: 0 var(--sp-3);
187
+ border-radius: var(--r-inner);
188
+ color: var(--ink-2);
189
+ font-size: var(--fs-sm); font-weight: 600;
190
+ transition: box-shadow var(--t), color var(--t), background-color var(--t);
191
+ }
192
+ .rail-item .ico { flex: none; width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
193
+ .rail-item:hover { box-shadow: var(--raise-sm); color: var(--ink); }
194
+ .rail-item.active {
195
+ background: var(--card);
196
+ box-shadow: var(--sink-sm);
197
+ color: var(--accent-ink);
198
+ }
199
+ .rail-item.active .ico { color: var(--accent); }
200
+ .rail-foot { margin-top: auto; padding: 0 var(--sp-2); }
201
+ .rail-version { color: var(--ink-2); font-size: var(--fs-xs); }
202
+
203
+ .panel {
204
+ min-width: 0;
205
+ min-height: 100vh;
206
+ padding: var(--sp-4) var(--sp-6) var(--sp-6) var(--sp-4);
207
+ display: flex;
208
+ flex-direction: column;
209
+ gap: var(--sp-6);
210
+ }
211
+ body[data-tab="tools"] .grid { flex: 1 1 auto; align-content: stretch; }
212
+
213
+ /* --------------------------------------------------------------- topbar --- */
80
214
 
81
- /* ---------- 3. topbar ---------- */
82
215
  .topbar {
83
- position: fixed;
84
- top: 0; left: 0; right: 0;
85
- z-index: 30;
86
- height: var(--topbar-h);
216
+ position: sticky;
217
+ top: 0;
218
+ z-index: 20;
87
219
  display: flex;
88
220
  align-items: center;
89
- justify-content: space-between;
90
- gap: 12px;
91
- padding: 0 var(--pad-page);
92
- background: var(--page);
221
+ gap: var(--sp-4);
222
+ min-height: 56px;
223
+ margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-6)) 0 calc(-1 * var(--sp-4));
224
+ padding: var(--sp-2) var(--sp-6) var(--sp-2) var(--sp-4);
225
+ background: var(--bg);
93
226
  }
94
- .topbar-title { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
95
227
  .topbar h1 {
96
- margin: 0;
97
- font-size: 24px;
98
- line-height: 30px;
228
+ font-size: var(--fs-lg);
229
+ line-height: 34px;
99
230
  font-weight: 700;
100
- letter-spacing: -0.02em;
101
- color: var(--text);
231
+ letter-spacing: -.01em;
232
+ white-space: nowrap;
102
233
  }
103
- .link-button {
104
- align-self: flex-start;
105
- padding: 0;
106
- border: 0;
107
- background: transparent;
108
- color: var(--accent);
109
- font: inherit;
110
- font-size: 13px;
111
- line-height: 18px;
112
- cursor: pointer;
234
+ .topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-3); }
235
+
236
+ .seg {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: var(--sp-1);
240
+ padding: var(--sp-1);
241
+ border-radius: var(--r-inner);
242
+ background: var(--bg);
243
+ box-shadow: var(--sink-sm);
244
+ }
245
+ .seg-item {
246
+ display: inline-flex;
247
+ align-items: center;
248
+ height: 32px;
249
+ padding: 0 var(--sp-4);
250
+ border-radius: var(--r-chip);
251
+ color: var(--ink-2);
252
+ font-size: var(--fs-sm);
253
+ font-weight: 600;
254
+ transition: box-shadow var(--t), color var(--t), background-color var(--t);
113
255
  }
256
+ .seg-item:hover { color: var(--ink); }
257
+ .seg-item.active {
258
+ background: var(--card);
259
+ box-shadow: var(--raise-sm);
260
+ color: var(--accent-ink);
261
+ }
262
+
114
263
  .icon-button {
115
- display: grid;
116
- place-items: center;
117
- flex: 0 0 40px;
118
- width: 40px;
264
+ width: 40px; height: 40px;
265
+ border-radius: var(--r-chip);
266
+ display: grid; place-items: center;
267
+ background: var(--card);
268
+ color: var(--ink-2);
269
+ box-shadow: var(--raise-btn);
270
+ transition: box-shadow var(--t), color var(--t);
271
+ }
272
+ .icon-button svg { width: 20px; height: 20px; }
273
+ .icon-button:hover { box-shadow: var(--raise-hover); color: var(--ink); }
274
+ .icon-button:active { box-shadow: var(--sink); }
275
+ .icon-button-accent { color: var(--accent); }
276
+
277
+ .ghost-button,
278
+ .primary-button {
119
279
  height: 40px;
120
- padding: 0;
121
- border: 0;
122
- border-radius: 50%;
123
- background: var(--tone);
124
- color: var(--text);
125
- cursor: pointer;
280
+ padding: 0 var(--sp-4);
281
+ border-radius: var(--r-chip);
282
+ font-size: var(--fs-sm);
283
+ font-weight: 600;
284
+ display: inline-flex;
285
+ align-items: center;
286
+ background: var(--card);
287
+ box-shadow: var(--raise-btn);
288
+ transition: box-shadow var(--t), color var(--t), background-color var(--t);
289
+ }
290
+ .ghost-button { color: var(--ink-2); }
291
+ .ghost-button:hover { box-shadow: var(--raise-hover); color: var(--ink); }
292
+ .primary-button { color: var(--accent); box-shadow: var(--raise-sm); }
293
+ .primary-button:hover { box-shadow: var(--raise-hover); }
294
+ .ghost-button:active,
295
+ .primary-button:active,
296
+ .ghost-button.is-pressed,
297
+ .primary-button.is-pressed {
298
+ background: var(--bg);
299
+ box-shadow: var(--sink);
300
+ color: var(--accent-ink);
301
+ }
302
+ .ghost-button:disabled,
303
+ .primary-button:disabled {
304
+ color: var(--ink-3);
305
+ box-shadow: var(--raise-sm);
306
+ cursor: not-allowed;
307
+ opacity: .7;
126
308
  }
127
- .icon-button-accent { background: var(--accent); color: #fff; }
128
309
 
129
- /* ---------- 4. cards ---------- */
130
- .cards { display: grid; grid-template-columns: 1fr; gap: var(--gap-card); }
131
- .cards > [data-card-id] { grid-column: span 1; min-width: 0; }
132
- .card, .masthead, .add-cards {
310
+ /* ----------------------------------------------------------------- grid --- */
311
+
312
+ .grid {
313
+ display: grid;
314
+ grid-template-columns: repeat(12, minmax(0, 1fr));
315
+ gap: var(--sp-4);
316
+ align-items: stretch;
317
+ }
318
+ .span-3 { grid-column: span 3; }
319
+ .span-4 { grid-column: span 4; }
320
+ .span-6 { grid-column: span 6; }
321
+ .span-8 { grid-column: span 8; }
322
+ .span-12 { grid-column: span 12; }
323
+ .h-120 { min-height: 120px; }
324
+ .h-176 { min-height: 176px; }
325
+ .h-200 { min-height: 200px; }
326
+ .h-208 { min-height: 208px; }
327
+ .h-232 { min-height: 232px; }
328
+ .h-280 { min-height: 280px; }
329
+ .h-380 { min-height: 380px; }
330
+ .h-420 { min-height: 380px; }
331
+
332
+ /* ---------------------------------------------------------------- cards --- */
333
+
334
+ .card {
133
335
  position: relative;
134
- padding: var(--pad-card);
336
+ min-width: 0;
337
+ overflow: hidden;
338
+ display: flex;
339
+ flex-direction: column;
340
+ gap: var(--sp-3);
341
+ padding: var(--sp-6);
342
+ border-radius: var(--r-card);
135
343
  background: var(--card);
136
- border: 0;
137
- border-radius: var(--radius-card);
138
- box-shadow: var(--shadow-e1);
344
+ box-shadow: var(--raise);
139
345
  }
140
- .card-flush { padding: 0; background: transparent; box-shadow: none; border-radius: 0; }
141
- .card-head, .section-head {
346
+ .card-head {
142
347
  display: flex;
143
348
  align-items: center;
144
- gap: 8px;
145
- min-height: 22px;
146
- margin-bottom: 12px;
349
+ gap: var(--sp-3);
350
+ min-height: 28px;
351
+ flex: none;
147
352
  }
148
- .card-head h2, .section-head h2, .trace-summary h2, .memory-head h2 {
149
- margin: 0;
150
- font-size: 17px;
151
- line-height: 22px;
152
- font-weight: 600;
153
- letter-spacing: -0.01em;
353
+ .card-ico {
354
+ flex: none;
355
+ width: 36px; height: 36px;
356
+ border-radius: var(--r-chip);
357
+ display: grid; place-items: center;
358
+ background: var(--card);
359
+ box-shadow: var(--raise-sm);
360
+ color: var(--accent);
361
+ }
362
+ .card-ico svg {
363
+ width: 20px; height: 20px;
364
+ fill: none; stroke: currentColor; stroke-width: 1.5;
365
+ stroke-linecap: round; stroke-linejoin: round;
154
366
  }
155
- .card-icon { display: grid; place-items: center; flex: 0 0 18px; width: 18px; height: 18px; color: var(--text-2); }
156
- .card-icon svg { display: block; width: 18px; height: 18px; }
157
- .card-aside, .section-head .hint, .trace-summary .hint {
367
+ .card-head h2 {
368
+ font-size: var(--fs-md);
369
+ line-height: 28px;
370
+ font-weight: 700;
371
+ white-space: nowrap;
372
+ overflow: hidden;
373
+ text-overflow: ellipsis;
374
+ }
375
+ .card-trail {
158
376
  margin-left: auto;
159
- color: var(--text-3);
160
- font-size: 13px;
161
- line-height: 18px;
377
+ color: var(--ink-2);
378
+ font-size: var(--fs-xs);
379
+ line-height: 24px;
162
380
  white-space: nowrap;
381
+ font-variant-numeric: tabular-nums;
382
+ max-width: 55%;
383
+ overflow: hidden;
384
+ text-overflow: ellipsis;
385
+ }
386
+ .card-trail.up { color: var(--accent-ink); }
387
+ .card-trail.down { color: var(--ink-2); }
388
+
389
+ .hint,
390
+ .state-note {
391
+ color: var(--ink-2);
392
+ font-size: var(--fs-xs);
393
+ line-height: 18px;
394
+ }
395
+ .state-note { color: var(--ink); }
396
+ .group-title {
397
+ color: var(--ink-2);
398
+ font-size: var(--fs-xs);
399
+ line-height: 18px;
400
+ letter-spacing: .08em;
401
+ text-transform: uppercase;
402
+ }
403
+ .card-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: auto; padding-top: var(--sp-1); }
404
+
405
+ .well {
406
+ border-radius: var(--r-inner);
407
+ background: var(--bg);
408
+ box-shadow: var(--sink-deep);
409
+ padding: var(--sp-3);
410
+ min-height: 0;
411
+ }
412
+
413
+ /* loading skeleton: solid plate, no gradient */
414
+ .is-booting .card > *:not(.card-head) { opacity: 0; }
415
+ .is-booting .card-trail { visibility: hidden; }
416
+ .is-booting .card::after {
417
+ content: "";
418
+ position: absolute;
419
+ inset: 76px var(--sp-6) var(--sp-6);
420
+ border-radius: var(--r-inner);
421
+ background: var(--bg);
422
+ box-shadow: var(--sink-deep);
423
+ animation: sk-pulse 1.2s ease-in-out infinite;
424
+ }
425
+ @keyframes sk-pulse {
426
+ 0%, 100% { opacity: .55; }
427
+ 50% { opacity: .95; }
428
+ }
429
+
430
+ /* ------------------------------------------------------------- status ---- */
431
+
432
+ .status-card {
433
+ flex-direction: row;
434
+ align-items: center;
435
+ gap: var(--sp-6);
436
+ }
437
+ .orb-wrap {
438
+ flex: none;
439
+ width: 96px; height: 96px;
440
+ border-radius: var(--r-card);
441
+ display: grid; place-items: center;
442
+ background: var(--bg);
443
+ box-shadow: var(--sink);
444
+ }
445
+ .orb {
446
+ position: relative;
447
+ width: 64px; height: 64px;
448
+ border-radius: var(--r-inner);
449
+ background: var(--accent);
450
+ box-shadow: inset -4px -4px 10px var(--orb-lo), inset 4px 4px 10px var(--orb-hi);
451
+ }
452
+ .orb-ring {
453
+ position: absolute;
454
+ inset: -8px;
455
+ border-radius: var(--r-card);
456
+ border: 1px solid var(--accent-ring);
457
+ }
458
+ .status-body { min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
459
+ .status-body h2 { font-size: var(--fs-md); line-height: 28px; font-weight: 700; }
460
+ .status-body .motivation {
461
+ color: var(--ink-2);
462
+ font-size: var(--fs-sm);
463
+ line-height: 22px;
464
+ display: -webkit-box;
465
+ -webkit-line-clamp: 2;
466
+ -webkit-box-orient: vertical;
467
+ overflow: hidden;
468
+ }
469
+ .status { display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--ink-2); font-size: var(--fs-xs); }
470
+ .status .dot {
471
+ width: 10px; height: 10px; border-radius: var(--r-chip);
472
+ background: var(--card);
473
+ box-shadow: var(--raise-sm);
163
474
  }
164
- .card-aside::after, .section-head .hint::after { content: ' ›'; opacity: 0.6; }
165
-
166
- /* masthead: orb centered, identity under it */
167
- .masthead { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; padding: 22px var(--pad-card) 18px; }
168
- .masthead .orb-wrap { width: 88px; height: 88px; flex: 0 0 88px; display: grid; place-items: center; }
169
- .identity { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
170
- .identity h1 { margin: 0; font-size: 20px; line-height: 26px; font-weight: 600; letter-spacing: -0.01em; }
171
- .motivation { margin: 0; color: var(--text-2); font-size: 15px; line-height: 20px; }
172
- .status { display: inline-flex; align-items: center; gap: 6px; margin-top: 2px; color: var(--text-3); font-size: 13px; line-height: 18px; }
173
- .status .dot { width: 6px; height: 6px; border-radius: 3px; background: var(--text-3); }
174
- .status.on .dot { background: var(--ok); }
175
- .status.off .dot { background: var(--danger); }
176
- .empty-hint { margin: 2px 0 0; color: var(--text-3); font-size: 12px; line-height: 16px; }
177
-
178
- /* orb (unchanged silhouette, sized for 88px box) */
179
- .orb { position: relative; width: 88px; height: 88px; border-radius: 50%; background: radial-gradient(circle at 50% 50%, rgba(86, 134, 254, 0) 0 15%, #5686fe 16% 100%); animation: breathe 7s ease-in-out infinite; }
180
- .orb::after { content: ''; position: absolute; inset: 0; border-radius: 50%; box-shadow: 0 0 28px 6px var(--orb-glow); opacity: 0.88; z-index: -1; pointer-events: none; }
181
- .orb-ring { position: absolute; inset: -8px; border-radius: 50%; border: 1px solid var(--line-strong); opacity: 0.55; animation: ring-breathe 7s ease-in-out infinite; pointer-events: none; }
182
- @keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.035); } }
183
- @keyframes ring-breathe { 0%, 100% { transform: scale(1); opacity: 0.55; } 50% { transform: scale(1.07); opacity: 0.22; } }
184
- @media (prefers-reduced-motion: reduce) { .orb, .orb-ring { animation: none; } }
185
-
186
- /* ---------- 5. figures / sub blocks ---------- */
187
- .sub-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-block); }
188
- .sub-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
189
- .subblock {
475
+ .status.on .dot { background: var(--accent); box-shadow: inset 1px 1px 2px rgba(0, 0, 0, .2); }
476
+ .status.off .dot { background: var(--bg); box-shadow: var(--sink-sm); }
477
+ .fact-list {
478
+ margin-left: auto;
190
479
  display: flex;
191
480
  flex-direction: column;
192
- gap: 6px;
193
- min-width: 0;
194
- padding: 14px;
195
- background: var(--block);
196
- border-radius: var(--radius-block);
197
- }
198
- .sub-label { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--text-2); font-size: 12px; line-height: 16px; }
199
- .sub-trend { display: inline-flex; align-items: baseline; gap: 4px; color: var(--text-3); font-size: 12px; line-height: 16px; }
200
- .sub-trend b { font-weight: 600; }
201
- .delta { font-size: 12px; color: var(--text-3); font-variant-numeric: tabular-nums; }
202
- .delta.up { color: var(--ok); }
203
- .delta.down { color: var(--danger); }
204
- .sub-value { display: flex; align-items: baseline; gap: 6px; letter-spacing: -0.02em; }
205
- .sub-value strong { font-size: 20px; line-height: 26px; font-weight: 700; }
206
- .channels-card .sub-value strong { font-size: 20px; line-height: 26px; }
207
- .mood-card .sub-value strong { font-size: 30px; line-height: 34px; }
208
- .unit { display: none; }
209
- .sub-status { margin-left: auto; color: var(--text-2); font-size: 13px; line-height: 18px; letter-spacing: 0; }
210
- .sub-note { color: var(--text-3); font-size: 12px; line-height: 16px; min-height: 16px; }
211
- .figure-caption { color: var(--text-3); font-size: 12px; line-height: 16px; }
212
- .mood-card .figure-caption { display: none; }
213
- .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
214
- .chip { display: inline-flex; align-items: baseline; gap: 6px; padding: 5px 12px; background: var(--block); border-radius: var(--radius-pill); font-size: 12px; line-height: 16px; }
215
- .chip b { color: var(--text-3); font-size: 12px; font-weight: 400; }
216
- .chip strong { color: var(--text); font-size: 13px; font-weight: 600; }
217
-
218
- /* single-metric mood card: one hero number, drop the duplicated tension block */
219
- .mood-card .sub-grid.two { grid-template-columns: 1fr; }
220
- .mood-card .sub-grid.two > .subblock + .subblock { display: none; }
221
-
222
- /* progress bar (6px, radius 3) */
223
- .bar { position: relative; height: 6px; border-radius: 3px; background: var(--block); overflow: visible; }
224
- .bar i { display: block; height: 100%; width: 0; border-radius: 3px; background: var(--accent); transition: width .4s ease; }
225
- .bar-over { position: absolute; top: 0; left: 65%; height: 100%; width: 0; border-radius: 3px; background: var(--warn); }
226
- .subblock .bar { margin-top: 2px; background: var(--card); }
227
- .subblock .bar i { background: var(--accent); }
228
- .subblock .bar-over { background: var(--warn); }
229
- .bar-legend { display: flex; align-items: center; gap: 12px; margin-top: 6px; color: var(--text-3); font-size: 12px; line-height: 16px; }
230
- .legend-dot { display: inline-block; width: 6px; height: 6px; margin-right: 4px; border-radius: 3px; background: var(--accent); }
231
- .legend-dot.warn { background: var(--warn); }
232
-
233
- /* chart */
234
- canvas#moodChart { display: block; width: 100%; height: 150px; }
235
-
236
- /* ---------- 6. lists ---------- */
237
- .memory-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; max-height: 300px; overflow: auto; }
238
- .memory-list li { display: block; padding: 12px 0; border-bottom: 1px solid var(--line); }
239
- .memory-list li:first-child { padding-top: 0; }
240
- .memory-list li:last-child { border-bottom: 0; padding-bottom: 0; }
241
- .memory-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
242
- .memory-list time { color: var(--text-3); font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums; }
243
- .memory-tag { padding: 1px 8px; border-radius: var(--radius-pill); background: var(--block); color: var(--text-2); font-size: 11px; line-height: 15px; }
244
- .memory-text { display: block; color: var(--text); font-size: 15px; line-height: 22px; overflow-wrap: anywhere; }
245
- .memory-list li.empty { color: var(--text-3); border: 0; font-size: 13px; padding: 4px 0; }
246
- .memory-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
247
- .memory-stat { display: flex; flex-direction: column; gap: 2px; padding: 14px; background: var(--block); border-radius: var(--radius-block); }
248
- .memory-stat span { color: var(--text-2); font-size: 12px; line-height: 16px; }
249
- .memory-stat strong { font-size: 22px; line-height: 28px; font-weight: 700; letter-spacing: -0.02em; }
250
- .memory-stat em { color: var(--text-2); font-size: 12px; font-style: normal; }
251
- .memory-summary-card .capacity { margin-top: 14px; }
252
- .capacity { margin-top: 12px; }
253
- .capacity .bar { margin-top: 6px; }
254
-
255
- /* relation */
256
- .relation-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 16px; }
257
- .relation-col { display: flex; flex-direction: column; gap: 2px; }
258
- .relation-label { color: var(--text-2); font-size: 12px; line-height: 16px; }
259
- .relation-value { font-size: 24px; line-height: 28px; font-weight: 700; letter-spacing: -0.02em; }
260
- .relation-note { margin: 2px 0 0; color: var(--text-3); font-size: 12px; line-height: 16px; }
261
- .relation-foot { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); color: var(--text-2); font-size: 12px; line-height: 18px; }
262
-
263
- /* trace */
264
- .trace-card { padding: 0; }
265
- .trace-summary { display: flex; align-items: center; gap: 8px; padding: var(--pad-card); cursor: pointer; list-style: none; }
266
- .trace-summary::-webkit-details-marker { display: none; }
267
- .trace-list { display: flex; flex-direction: column; gap: 12px; padding: 0 var(--pad-card) var(--pad-card); }
268
- .trace-list .empty { margin: 0; color: var(--text-3); font-size: 13px; }
269
- .trace-row { padding-top: 12px; border-top: 1px solid var(--line); }
270
- .trace-row:first-child { padding-top: 0; border-top: 0; }
271
- .trace-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 4px; color: var(--text-3); font-size: 12px; }
272
- .trace-grid { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 2px 8px; margin: 0; font-size: 12px; line-height: 18px; }
273
- .trace-grid dt { color: var(--text-3); }
274
- .trace-grid dd { margin: 0; color: var(--text-2); overflow-wrap: anywhere; }
275
- .trace-badge { padding: 0 6px; border-radius: var(--radius-pill); background: var(--block); color: var(--text-3); font-size: 11px; }
276
-
277
- /* ---------- 7. forms ---------- */
278
- .persona-text {
279
- width: 100%;
280
- min-height: 96px;
281
- resize: vertical;
282
- padding: 12px;
283
- color: var(--text);
284
- background: var(--block);
285
- border: 0;
286
- border-radius: var(--radius-field);
287
- font: inherit;
288
- font-size: 15px;
289
- line-height: 22px;
290
- outline: none;
481
+ gap: var(--sp-2);
482
+ min-width: 148px;
483
+ padding: var(--sp-3);
484
+ border-radius: var(--r-inner);
485
+ background: var(--bg);
486
+ box-shadow: var(--sink-sm);
291
487
  }
292
- .persona-text:focus { box-shadow: 0 0 0 2px var(--accent-soft); }
293
- .persona-actions { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
294
- .persona-save {
295
- min-height: 40px;
296
- padding: 0 18px;
297
- font: inherit;
298
- font-size: 15px;
299
- font-weight: 600;
300
- color: #fff;
488
+ .fact-list div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
489
+ .fact-list dt { color: var(--ink-2); font-size: var(--fs-xs); }
490
+ .fact-list dd { color: var(--ink); font-size: var(--fs-sm); font-weight: 700; }
491
+
492
+ /* --------------------------------------------------------- metric cards -- */
493
+
494
+ .metric { display: flex; align-items: baseline; gap: var(--sp-2); }
495
+ .metric strong {
496
+ font-size: var(--fs-xl);
497
+ line-height: 38px;
498
+ font-weight: 700;
499
+ font-variant-numeric: tabular-nums;
500
+ letter-spacing: -.02em;
501
+ }
502
+ .metric-sm strong { font-size: var(--fs-lg); line-height: 34px; }
503
+ .metric-word { color: var(--ink-2); font-size: var(--fs-xs); }
504
+ .metric-word:empty { display: none; }
505
+ body.is-empty .empty-hide { display: none; }
506
+
507
+ .subblock { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: auto; }
508
+ .data-row {
509
+ display: flex;
510
+ align-items: baseline;
511
+ justify-content: space-between;
512
+ gap: var(--sp-2);
513
+ color: var(--ink-2);
514
+ font-size: var(--fs-xs);
515
+ }
516
+ .data-row b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
517
+ .data-row b.up { color: var(--accent-ink); }
518
+ .data-row b.down { color: var(--ink-2); }
519
+
520
+ .bar {
521
+ position: relative;
522
+ height: 10px;
523
+ border-radius: var(--r-chip);
524
+ background: var(--bg);
525
+ box-shadow: var(--sink-sm);
526
+ overflow: hidden;
527
+ }
528
+ .bar > i {
529
+ position: absolute;
530
+ inset: 2px auto 2px 2px;
531
+ width: 0;
532
+ border-radius: var(--r-chip);
301
533
  background: var(--accent);
302
- border: 0;
303
- border-radius: var(--radius-field);
304
- cursor: pointer;
534
+ box-shadow: 1px 1px 2px var(--shadow-dark);
535
+ }
536
+ .bar > .bar-over {
537
+ position: absolute;
538
+ top: 0; bottom: 0;
539
+ left: 65%;
540
+ width: 0;
541
+ background: var(--ink-2);
542
+ opacity: .35;
305
543
  }
306
- .persona-save:disabled { opacity: 0.55; cursor: progress; }
307
- .persona-preview { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px 16px; margin-top: 14px; font-size: 12px; line-height: 18px; }
308
- .persona-preview div { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; color: var(--text-3); }
309
- .persona-preview strong { color: var(--text); font-weight: 600; font-size: 13px; }
310
- .persona-status-error { color: var(--danger); }
311
- .persona-status-ok { color: var(--ok); }
312
544
 
313
- .model-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; }
314
- .field { display: flex; flex-direction: column; gap: 6px; font-size: 12px; line-height: 16px; color: var(--text-2); }
315
- .field input, .field select {
316
- height: 40px;
317
- padding: 0 12px;
318
- font: inherit;
319
- font-size: 15px;
320
- color: var(--text);
321
- background: var(--block);
322
- border: 0;
323
- border-radius: var(--radius-field);
324
- outline: none;
545
+ /* ---------------------------------------------------------- data lists --- */
546
+
547
+ .data-list { display: flex; flex-direction: column; gap: 2px; }
548
+ .data-list div {
549
+ display: flex;
550
+ align-items: baseline;
551
+ justify-content: space-between;
552
+ gap: var(--sp-4);
553
+ padding: var(--sp-2) var(--sp-1);
554
+ border-radius: var(--r-chip);
325
555
  }
326
- .field input:focus, .field select:focus { box-shadow: 0 0 0 2px var(--accent-soft); }
327
- .model-actions { display: flex; align-items: center; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
328
- .model-test {
329
- min-height: 40px;
330
- padding: 0 16px;
331
- font: inherit;
332
- font-size: 15px;
333
- color: var(--text);
334
- background: var(--block);
335
- border: 0;
336
- border-radius: var(--radius-field);
337
- cursor: pointer;
556
+
557
+ .data-list dt { color: var(--ink-2); font-size: var(--fs-xs); white-space: nowrap; }
558
+ .data-list dd {
559
+ color: var(--ink);
560
+ font-size: var(--fs-sm);
561
+ font-weight: 700;
562
+ font-variant-numeric: tabular-nums;
563
+ text-align: right;
564
+ min-width: 0;
565
+ overflow: hidden;
566
+ text-overflow: ellipsis;
567
+ white-space: nowrap;
338
568
  }
569
+ .data-list dd small { color: var(--ink-2); font-size: var(--fs-xs); font-weight: 400; margin-left: var(--sp-1); }
339
570
 
340
- /* ---------- 8. switches + advanced ---------- */
341
- .switches { display: flex; flex-direction: column; gap: 10px; }
342
- .switch-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px; background: var(--block); border-radius: var(--radius-block); }
343
- .switch-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
344
- .switch-label { font-size: 15px; line-height: 20px; font-weight: 600; }
345
- .switch-desc { color: var(--text-3); font-size: 12px; line-height: 16px; }
346
- .switch-state { color: var(--text-2); font-size: 12px; line-height: 16px; }
347
- .switch-row input { accent-color: var(--accent); width: 22px; height: 22px; }
348
-
349
- .advanced-info { margin: 0; display: flex; flex-direction: column; }
350
- .advanced-info div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line); }
351
- .advanced-info div:last-child { border-bottom: 0; }
352
- .advanced-info dt { color: var(--text-2); font-size: 12px; line-height: 16px; }
353
- .advanced-info dd { margin: 0; color: var(--text); font-size: 15px; line-height: 20px; text-align: right; }
354
- .advanced-actions { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
355
- .advanced-button {
356
- min-height: 36px;
357
- padding: 0 14px;
358
- font: inherit;
359
- font-size: 14px;
360
- color: var(--text);
361
- background: var(--block);
362
- border: 0;
363
- border-radius: var(--radius-field);
364
- cursor: pointer;
571
+ .avg-card .data-list div { padding: var(--sp-1); }
572
+ .data-list-inline {
573
+ display: grid;
574
+ grid-template-columns: repeat(3, minmax(0, 1fr));
575
+ column-gap: var(--sp-3);
576
+ align-content: start;
365
577
  }
578
+ .data-inline { display: flex; align-items: baseline; gap: var(--sp-2); }
579
+ .data-inline span { color: var(--ink-2); font-size: var(--fs-xs); }
580
+ .data-inline b { font-size: var(--fs-sm); font-weight: 700; }
366
581
 
367
- /* three-column stats */
368
- .triple { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
369
- .triple-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 14px; background: var(--block); border-radius: var(--radius-block); }
370
- .triple-col strong { font-size: 24px; line-height: 28px; font-weight: 700; letter-spacing: -0.02em; }
371
- .triple-col span { color: var(--text-2); font-size: 12px; line-height: 16px; }
582
+ /* ------------------------------------------------------------- triple ---- */
372
583
 
373
- /* footer */
374
- .footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 2px 4px 0; color: var(--text-3); font-size: 12px; line-height: 16px; }
584
+ .triple { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3); }
585
+ .triple-col {
586
+ display: flex;
587
+ flex-direction: column;
588
+ gap: var(--sp-1);
589
+ min-width: 0;
590
+ padding: var(--sp-3);
591
+ border-radius: var(--r-inner);
592
+ background: var(--bg);
593
+ box-shadow: var(--sink-sm);
594
+ }
595
+ .triple-col span { color: var(--ink-2); font-size: var(--fs-xs); line-height: 18px; }
596
+ .triple-col strong {
597
+ font-size: var(--fs-md);
598
+ line-height: 28px;
599
+ font-weight: 700;
600
+ font-variant-numeric: tabular-nums;
601
+ white-space: nowrap;
602
+ overflow: hidden;
603
+ text-overflow: ellipsis;
604
+ }
375
605
 
376
- /* ---------- 9. bottom nav ---------- */
377
- .tabbar {
378
- position: fixed;
379
- left: 50%;
380
- bottom: calc(12px + env(safe-area-inset-bottom, 0px));
381
- z-index: 35;
606
+ /* ------------------------------------------------------------- chart ----- */
607
+
608
+ .chart-well { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; padding: var(--sp-3); }
609
+ .chart-well canvas { display: block; width: 100%; height: 150px; }
610
+ .chart-empty { margin: auto 0; color: var(--ink-2); font-size: var(--fs-xs); line-height: 18px; }
611
+
612
+ /* ------------------------------------------------------------- memory ---- */
613
+
614
+ .table-head,
615
+ .memory-list li {
616
+ display: grid;
617
+ grid-template-columns: 96px 64px minmax(0, 1fr);
618
+ gap: var(--sp-3);
619
+ align-items: baseline;
620
+ }
621
+ .table-head {
622
+ padding: 0 var(--sp-3) var(--sp-1);
623
+ color: var(--ink-2);
624
+ font-size: var(--fs-xs);
625
+ }
626
+ .list-well {
627
+ flex: 1 1 auto;
628
+ min-height: 0;
382
629
  display: flex;
383
- align-items: stretch;
384
- gap: 2px;
385
- width: min(430px, calc(100% - 32px));
386
- height: var(--nav-h);
387
- padding: 8px;
388
- transform: translateX(-50%);
389
- background: var(--tone);
390
- border-radius: var(--radius-pill);
391
- box-shadow: var(--shadow-e2);
392
- }
393
- .tab-item {
394
- flex: 1 1 0;
630
+ flex-direction: column;
631
+ overflow: hidden;
632
+ }
633
+ .memory-list {
634
+ list-style: none;
635
+ padding: 0;
395
636
  display: flex;
396
637
  flex-direction: column;
397
- align-items: center;
398
- justify-content: center;
399
- gap: 3px;
638
+ flex: 1 1 auto;
639
+ min-height: 0;
640
+ overflow: auto;
641
+ scrollbar-width: thin;
642
+ }
643
+ .memory-list li {
644
+ padding: var(--sp-2) var(--sp-3);
645
+ border-radius: var(--r-chip);
646
+ transition: box-shadow var(--t), background-color var(--t);
647
+ }
648
+ .memory-list li:hover { background: var(--card); box-shadow: var(--raise-sm); }
649
+ .memory-list time { color: var(--ink-2); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
650
+ .memory-kind { color: var(--ink-2); font-size: var(--fs-xs); }
651
+ .memory-text {
652
+ color: var(--ink);
653
+ font-size: var(--fs-sm);
654
+ line-height: 20px;
400
655
  min-width: 0;
401
- padding: 4px 6px;
402
- border: 0;
403
- border-radius: var(--radius-pill);
404
- background: transparent;
405
- color: var(--text-2);
406
- font: inherit;
407
- font-size: 11px;
408
- line-height: 13px;
409
- cursor: pointer;
410
- transition: background .15s ease, color .15s ease;
656
+ overflow: hidden;
657
+ text-overflow: ellipsis;
658
+ white-space: nowrap;
659
+ }
660
+ .memory-list li.empty {
661
+ display: block;
662
+ color: var(--ink-2);
663
+ font-size: var(--fs-sm);
664
+ padding: var(--sp-4) var(--sp-3);
411
665
  }
412
- .tab-item svg { display: block; width: 20px; height: 20px; }
413
- .tab-item.active { background: var(--accent); color: #fff; }
414
666
 
415
- /* tab visibility */
416
- .panel:not(.tab-dashboard) .masthead { display: none; }
417
- .layout-editing .masthead { display: flex; }
418
- .layout-editing .tabbar { display: none; }
667
+ /* ----------------------------------------------------------- relation ---- */
419
668
 
420
- /* ---------- 10. edit mode ---------- */
421
- .card-hide {
422
- display: none;
423
- position: absolute;
424
- top: -8px; right: -8px;
425
- z-index: 3;
426
- place-items: center;
427
- width: 28px; height: 28px;
428
- padding: 0;
429
- border: 0;
430
- border-radius: 50%;
431
- background: var(--danger);
432
- color: #fff;
433
- font-size: 18px;
434
- line-height: 1;
435
- cursor: pointer;
669
+ .relation { display: flex; flex-direction: column; gap: var(--sp-3); }
670
+ .relation .data-list { flex: 1 1 auto; }
671
+ .relation-foot {
672
+ display: flex;
673
+ gap: var(--sp-6);
674
+ padding: var(--sp-2) var(--sp-3);
675
+ border-radius: var(--r-inner);
676
+ background: var(--bg);
677
+ box-shadow: var(--sink-sm);
678
+ color: var(--ink-2);
679
+ font-size: var(--fs-xs);
436
680
  }
437
- .layout-editing .card-hide { display: grid; }
438
- .layout-editing .cards > [data-card-id] { touch-action: none; }
439
- .cards > [data-card-id].dragging { opacity: 0.8; outline: 2px dashed var(--accent); outline-offset: 2px; }
440
- [data-card-id].is-hidden, [data-card-id].tab-hidden { display: none !important; }
441
- .add-cards { border: 1px dashed var(--line-strong); box-shadow: none; }
442
- .add-cards h3 { margin: 0 0 12px; color: var(--text-2); font-size: 15px; line-height: 20px; font-weight: 600; }
443
- .add-list { display: flex; flex-wrap: wrap; gap: 8px; }
444
- .add-chip {
445
- min-height: 34px;
446
- padding: 0 12px;
447
- border: 0;
448
- border-radius: var(--radius-field);
449
- background: var(--block);
450
- color: var(--text);
681
+ .relation-foot b { color: var(--ink); font-weight: 700; margin-left: var(--sp-1); }
682
+
683
+ /* ------------------------------------------------------------ controls --- */
684
+
685
+ .field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
686
+ .field { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
687
+ .field-wide { grid-column: span 2; }
688
+ .field > span { color: var(--ink-2); font-size: var(--fs-xs); line-height: 16px; }
689
+ input[type="text"], input[type="url"], input[type="password"], input[type="number"], select, textarea {
690
+ width: 100%;
691
+ height: 40px;
692
+ background: var(--bg);
693
+ border: 1px solid transparent;
694
+ border-radius: var(--r-inner);
695
+ box-shadow: var(--sink-deep);
696
+ color: var(--ink);
451
697
  font: inherit;
452
- font-size: 14px;
698
+ font-size: var(--fs-sm);
699
+ padding: 0 var(--sp-3);
700
+ transition: box-shadow var(--t), border-color var(--t);
701
+ }
702
+ textarea { height: auto; min-height: 96px; padding: var(--sp-2) var(--sp-3); line-height: 22px; resize: vertical; }
703
+ input:hover, select:hover, textarea:hover { box-shadow: var(--sink); }
704
+ input:focus, select:focus, textarea:focus {
705
+ outline: none;
706
+ box-shadow: var(--sink-sm);
707
+ border-color: var(--accent);
708
+ }
709
+ input:disabled, select:disabled, textarea:disabled {
710
+ color: var(--ink-2);
711
+ background: var(--bg);
712
+ box-shadow: var(--sink-sm);
713
+ cursor: not-allowed;
714
+ }
715
+ ::placeholder { color: var(--ink-2); }
716
+ .field-block { gap: var(--sp-2); }
717
+ .persona-card .field-block { flex: 1 1 auto; min-height: 0; }
718
+ .persona-text { height: 100%; min-height: 140px; }
719
+
720
+ .switch-row {
721
+ display: flex;
722
+ align-items: center;
723
+ gap: var(--sp-3);
724
+ padding: var(--sp-2) var(--sp-3);
725
+ border-radius: var(--r-inner);
726
+ background: var(--bg);
727
+ box-shadow: var(--sink-sm);
453
728
  cursor: pointer;
729
+ transition: box-shadow var(--t);
454
730
  }
455
- .layout-toast {
456
- position: fixed;
457
- left: 50%;
458
- bottom: calc(var(--nav-h) + 32px + env(safe-area-inset-bottom, 0px));
459
- z-index: 30;
460
- transform: translateX(-50%);
461
- max-width: calc(100% - 32px);
462
- padding: 10px 16px;
463
- border: 0;
464
- border-radius: var(--radius-field);
731
+ .switch-row:hover { box-shadow: var(--sink-deep); }
732
+ .switch-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
733
+ .switch-label { font-size: var(--fs-sm); line-height: 20px; color: var(--ink); font-weight: 600; }
734
+ .switch-desc { color: var(--ink-2); font-size: var(--fs-xs); line-height: 16px; }
735
+ .switch-row input[type="checkbox"] {
736
+ margin-left: auto;
737
+ appearance: none;
738
+ flex: none;
739
+ position: relative;
740
+ width: 48px; height: 28px;
741
+ border-radius: var(--r-chip);
742
+ background: var(--bg);
743
+ box-shadow: var(--sink-deep);
744
+ cursor: pointer;
745
+ transition: box-shadow var(--t), background-color var(--t);
746
+ }
747
+ .switch-row input[type="checkbox"]::after {
748
+ content: "";
749
+ position: absolute;
750
+ top: 4px; left: 4px;
751
+ width: 20px; height: 20px;
752
+ border-radius: var(--r-chip);
465
753
  background: var(--card);
466
- box-shadow: var(--shadow-e2);
467
- color: var(--text);
468
- font-size: 13px;
469
- line-height: 18px;
754
+ box-shadow: var(--raise-sm);
755
+ transition: left var(--t), background-color var(--t);
470
756
  }
757
+ .switch-row input[type="checkbox"]:checked { background: var(--accent); }
758
+ .switch-row input[type="checkbox"]:checked::after { left: 24px; background: var(--knob); }
759
+ .switch-row input[type="checkbox"]:disabled { cursor: not-allowed; opacity: .7; }
471
760
 
472
- /* ---------- 11. desktop ---------- */
473
- @media (min-width: 600px) {
474
- :root { --pad-page: 24px; --pad-card: 20px; --radius-card: 32px; }
475
- body { font-size: 15px; }
476
- .panel { width: min(640px, 100%); }
477
- .tabbar { width: min(560px, calc(100% - 48px)); }
761
+ .switches {
762
+ display: grid;
763
+ grid-template-columns: repeat(2, minmax(0, 1fr));
764
+ column-gap: var(--sp-3);
765
+ row-gap: var(--sp-2);
766
+ align-content: start;
767
+ flex: 1 1 auto;
768
+ min-height: 0;
769
+ overflow: auto;
770
+ scrollbar-width: thin;
478
771
  }
479
- @media (max-width: 359px) {
480
- .sub-grid.two { grid-template-columns: 1fr; }
481
- .relation-grid { gap: 8px 12px; }
772
+ .switch-group {
773
+ grid-column: 1 / -1;
774
+ color: var(--ink-2);
775
+ font-size: var(--fs-xs);
776
+ line-height: 18px;
777
+ padding-top: var(--sp-2);
482
778
  }
779
+ .switches .switch-group:first-child { padding-top: 0; }
483
780
 
484
- /* ---------- 12. meta text ---------- */
485
- .hint { color: var(--text-3); font-size: 12px; line-height: 16px; }
486
- .persona-actions .hint, .model-actions .hint { flex: 1 1 auto; min-width: 0; }
487
- .empty { color: var(--text-3); font-size: 13px; line-height: 18px; }
781
+ #personaHint.persona-status-error, #personaStatus.persona-status-error { color: var(--danger); }
782
+ #personaHint.persona-status-ok, #personaStatus.persona-status-ok { color: var(--accent-ink); }
488
783
 
489
- /* --- expression length constraint card --- */
490
- .expression-fields {
784
+ .advanced-row {
785
+ display: flex;
786
+ align-items: center;
787
+ justify-content: space-between;
788
+ gap: var(--sp-6);
789
+ }
790
+ .advanced-row .card-actions { margin: 0; padding: 0; }
791
+
792
+ /* --------------------------------------------------------------- trace --- */
793
+
794
+ .trace-head-row,
795
+ .trace-row {
491
796
  display: grid;
492
- grid-template-columns: repeat(2, minmax(0, 1fr));
493
- gap: 10px 14px;
494
- margin-top: 10px;
495
- }
496
- .expression-fields[hidden] { display: none !important; }
497
- .expression-toggle { margin-top: 10px; }
498
- @media (max-width: 620px) {
499
- .expression-fields { grid-template-columns: 1fr; }
500
- }
501
-
502
- /* bug fix: whole channels block (title included) leaves non-dashboard tabs */
503
- .panel:not(.tab-dashboard):not(.layout-editing) .channels-wrap { display: none; }
504
-
505
- /* ---------- 13. layout guards (防止旧版/串版样式压扁版面) ---------- */
506
- html, body { overflow-x: clip; }
507
- body { max-width: 100%; }
508
- .panel { max-width: 100%; }
509
- .channels-wrap { min-width: 0; max-width: 100%; }
510
- .masthead { height: auto; max-height: none; overflow: visible; }
511
- .masthead .orb-wrap { min-width: 88px; min-height: 88px; overflow: visible; }
512
- .masthead .orb { flex: 0 0 auto; }
513
- .identity { align-self: center; width: 100%; }
514
- .channels-wrap { position: relative; }
515
- .channels-wrap > .channel-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
516
-
517
- /* ---------- 14. channels: four independent cards (2×2) ---------- */
518
- .channels-wrap { position: relative; }
519
- .channel-title-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 2px 4px 10px; }
520
- .channel-title-row h2 { margin: 0; font-size: 17px; line-height: 22px; font-weight: 600; letter-spacing: -0.01em; }
521
- .channel-aside { color: var(--text-3); font-size: 13px; line-height: 18px; }
522
- .channel-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
523
- .channel-card {
797
+ grid-template-columns: 48px minmax(0, 2.2fr) minmax(0, 1.6fr) minmax(0, 1fr) 64px minmax(0, 1.1fr);
798
+ gap: var(--sp-4);
799
+ align-items: baseline;
800
+ }
801
+ .trace-head-row {
802
+ color: var(--ink-2);
803
+ font-size: var(--fs-xs);
804
+ padding: 0 var(--sp-3);
805
+ }
806
+ .trace-list { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: auto; scrollbar-width: thin; }
807
+ .trace-row { padding: var(--sp-2) var(--sp-3); border-radius: var(--r-chip); }
808
+ .trace-row:nth-child(odd) { background: var(--card); box-shadow: var(--raise-sm); }
809
+ .trace-row span { font-size: var(--fs-xs); color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
810
+ .trace-row .trace-time { color: var(--ink-2); font-variant-numeric: tabular-nums; }
811
+ .trace-list .state-note { padding: var(--sp-4) var(--sp-3); }
812
+
813
+ /* -------------------------------------------------------------- footer --- */
814
+
815
+ .footer {
524
816
  display: flex;
525
- flex-direction: column;
526
- gap: 6px;
527
- min-width: 0;
528
- max-width: 100%;
529
- padding: 14px;
530
- background: var(--card);
531
- border-radius: 20px;
532
- box-shadow: var(--shadow-e1);
533
- }
534
- .channel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
535
- .channel-label { color: var(--text-2); font-size: 12px; line-height: 16px; }
536
- .channel-card .sub-trend { color: var(--text-3); font-size: 12px; line-height: 16px; }
537
- .channel-value { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; row-gap: 2px; min-width: 0; }
538
- .channel-value strong { font-size: 30px; line-height: 34px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
539
- .channel-card .sub-status { white-space: nowrap; margin-left: auto; color: var(--text-2); font-size: 13px; line-height: 18px; }
540
- .channel-card .sub-note { margin: 0; color: var(--text-3); font-size: 11px; line-height: 15px; min-height: 15px; overflow-wrap: anywhere; }
541
- .channel-card .bar { margin-top: 2px; }
542
- .channel-card .bar-legend { margin-top: 4px; gap: 10px; font-size: 11px; line-height: 15px; }
543
- .channel-card .bar-legend .legend-dot { width: 5px; height: 5px; border-radius: 2.5px; margin-right: 3px; }
544
- @media (min-width: 360px) {
545
- .channels-wrap .channel-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
817
+ justify-content: space-between;
818
+ gap: var(--sp-4);
819
+ padding: 0 var(--sp-2);
820
+ color: var(--ink-2);
821
+ font-size: var(--fs-xs);
822
+ line-height: 18px;
546
823
  }
547
- @media (max-width: 359px) {
548
- .channels-wrap .channel-grid { grid-template-columns: 1fr; }
824
+
825
+ .layout-toast {
826
+ position: fixed;
827
+ left: 50%;
828
+ bottom: var(--sp-6);
829
+ padding: var(--sp-3) var(--sp-6);
830
+ border-radius: var(--r-inner);
831
+ background: var(--card);
832
+ box-shadow: var(--raise);
833
+ color: var(--ink);
834
+ font-size: var(--fs-sm);
835
+ z-index: 40;
549
836
  }
550
837
 
551
- /* --- model card: embedding / rerank sections --- */
552
- .model-section-title {
553
- margin: 14px 0 8px;
554
- color: var(--text-2);
555
- font-size: 11px;
556
- line-height: 14px;
557
- font-weight: 600;
838
+ /* ---------------------------------------------------------- edit mode ---- */
839
+
840
+ .card-hide {
841
+ display: none;
842
+ position: absolute;
843
+ top: var(--sp-3);
844
+ right: var(--sp-3);
845
+ width: 32px; height: 32px;
846
+ border-radius: var(--r-chip);
847
+ place-items: center;
848
+ background: var(--card);
849
+ box-shadow: var(--raise-sm);
850
+ color: var(--accent);
851
+ font-size: var(--fs-md);
852
+ line-height: 1;
853
+ font-weight: 700;
854
+ z-index: 3;
855
+ transition: box-shadow var(--t);
558
856
  }
559
- .model-card .model-section-title:first-of-type { margin-top: 0; }
560
- .rerank-toggle { margin: 0 0 10px; }
561
- .rerank-grid[hidden] { display: none !important; }
857
+ .card-hide:hover { box-shadow: var(--raise-hover); }
858
+ .card-hide:active { box-shadow: var(--sink-sm); }
859
+ body.layout-editing .card-hide { display: grid; }
860
+ body.layout-editing .card { cursor: grab; }
861
+ body.layout-editing .card.dragging { opacity: .6; cursor: grabbing; }
862
+ body.layout-editing .card.is-hidden { display: none; }
863
+ .card.tab-off, .is-hidden { display: none !important; }
864
+
865
+ .add-cards {
866
+ padding: var(--sp-6);
867
+ border-radius: var(--r-card);
868
+ background: var(--card);
869
+ box-shadow: var(--raise);
870
+ }
871
+ .add-cards h3 { font-size: var(--fs-sm); font-weight: 700; margin-bottom: var(--sp-3); color: var(--ink); }
872
+ .add-list { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
873
+ .add-chip {
874
+ padding: var(--sp-2) var(--sp-4);
875
+ border-radius: var(--r-chip);
876
+ background: var(--card);
877
+ box-shadow: var(--raise-sm);
878
+ color: var(--ink-2);
879
+ font-size: var(--fs-xs);
880
+ transition: box-shadow var(--t), color var(--t);
881
+ }
882
+ .add-chip:hover { box-shadow: var(--raise-hover); color: var(--ink); }
883
+ .add-chip:active { box-shadow: var(--sink-sm); }
562
884
 
563
- /* ---------- 15. desktop (>=1024): left rail + 12-col dashboard ---------- */
564
- .rail, .desk { display: none; }
885
+ /* ------------------------------------------------------------ tabbar ----- */
565
886
 
566
- @media (min-width: 1024px) {
567
- :root {
568
- --rail-w: 220px;
569
- --radius-card: 32px;
570
- --pad-card: 20px;
571
- --gap-card: 12px;
572
- }
573
- body { padding: 0; }
574
- body.rail-collapsed { --rail-w: 64px; }
887
+ .tabbar { display: none; }
575
888
 
576
- .panel {
577
- width: auto;
578
- max-width: none;
579
- min-height: 100vh;
580
- margin: 0 0 0 var(--rail-w);
581
- padding: 16px 24px 24px 16px;
582
- display: grid;
583
- grid-template-columns: repeat(12, minmax(0, 1fr));
584
- gap: 12px;
585
- align-content: start;
586
- transition: margin-left 160ms ease;
587
- }
889
+ /* ============================================================ mobile ===== */
588
890
 
589
- /* --- left rail --- */
590
- .rail {
591
- position: fixed;
592
- inset: 0 auto 0 0;
593
- z-index: 40;
594
- width: var(--rail-w);
595
- display: flex;
596
- flex-direction: column;
597
- gap: 6px;
598
- padding: 12px 10px;
599
- background: var(--page);
600
- border-right: 1px solid var(--line);
601
- overflow: hidden;
602
- transition: width 160ms ease, padding 160ms ease;
891
+ @media (max-width: 1023px) {
892
+ body { grid-template-columns: minmax(0, 1fr); }
893
+ .rail { display: none; }
894
+ .panel {
895
+ padding: var(--sp-3) var(--sp-3) calc(96px + env(safe-area-inset-bottom, 0px));
896
+ gap: var(--sp-4);
603
897
  }
604
- .rail-toggle {
605
- display: grid;
606
- place-items: center;
607
- width: 40px;
608
- height: 40px;
609
- margin: 0 0 8px 2px;
610
- padding: 0;
611
- border: 0;
612
- border-radius: 10px;
613
- background: transparent;
614
- color: var(--text-2);
615
- cursor: pointer;
616
- transition: background 160ms ease, color 160ms ease;
898
+ .topbar {
899
+ min-height: 52px;
900
+ margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-3)) 0;
901
+ padding: var(--sp-2) var(--sp-3);
617
902
  }
618
- .rail-toggle:hover { background: rgba(255, 255, 255, 0.04); color: var(--text); }
619
- .rail-toggle svg { width: 20px; height: 20px; }
620
- .rail-nav { display: flex; flex-direction: column; gap: 2px; }
621
- .rail-item {
622
- position: relative;
903
+ .topbar h1 { font-size: var(--fs-md); line-height: 28px; }
904
+ .seg { display: none; }
905
+ .grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
906
+ .span-3, .span-4, .span-6, .span-8, .span-12 { grid-column: auto; }
907
+ .h-120, .h-176, .h-200, .h-208, .h-232, .h-280, .h-380, .h-420 { min-height: 0; }
908
+ .card { padding: var(--sp-4); gap: var(--sp-3); border-radius: var(--r-card); }
909
+
910
+ .status-card { flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
911
+ .fact-list { width: 100%; min-width: 0; flex-direction: row; gap: var(--sp-4); }
912
+ .fact-list div { flex: 1; }
913
+ .orb-wrap { width: 80px; height: 80px; }
914
+ .orb { width: 52px; height: 52px; }
915
+
916
+ .memory-list { flex: 0 1 auto; }
917
+ .table-head, .memory-list li { grid-template-columns: 88px 56px minmax(0, 1fr); }
918
+ .memory-text { white-space: normal; }
919
+ .field-grid { grid-template-columns: minmax(0, 1fr); }
920
+ .field-wide { grid-column: auto; }
921
+ .data-list-inline { grid-template-columns: minmax(0, 1fr); }
922
+ .switches { grid-template-columns: minmax(0, 1fr); overflow: visible; }
923
+ .trace-head-row { display: none; }
924
+ .trace-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-1) var(--sp-3); }
925
+ .trace-row span::before { content: attr(data-label) " "; color: var(--ink-2); }
926
+ .advanced-row { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
927
+ .is-booting .card::after { inset: 76px var(--sp-4) var(--sp-4); }
928
+ .card-actions { gap: var(--sp-2); }
929
+ .ghost-button, .primary-button { height: 38px; }
930
+
931
+ .tabbar {
623
932
  display: flex;
624
- align-items: center;
625
- gap: 10px;
626
- height: 40px;
627
- padding: 0 12px;
628
- border: 0;
629
- border-radius: 8px;
630
- background: transparent;
631
- color: var(--text-2);
632
- font: inherit;
633
- font-size: 14px;
634
- line-height: 20px;
635
- text-align: left;
636
- white-space: nowrap;
637
- overflow: hidden;
638
- cursor: pointer;
639
- transition: background 160ms ease, color 160ms ease;
640
- }
641
- .rail-item svg { flex: 0 0 20px; width: 20px; height: 20px; }
642
- .rail-item:hover { background: rgba(255, 255, 255, 0.04); color: var(--text); }
643
- .rail-item.active { background: rgba(255, 255, 255, 0.06); color: var(--text); }
644
- .rail-item.active::before {
645
- content: '';
646
- position: absolute;
647
- left: 0;
648
- top: 8px;
649
- bottom: 8px;
650
- width: 2px;
651
- border-radius: 2px;
652
- background: var(--accent);
653
- }
654
- body.rail-collapsed .rail-item { justify-content: center; padding: 0; }
655
- body.rail-collapsed .rail-item span { display: none; }
656
-
657
- /* --- header --- */
658
- .topbar { position: static; height: 56px; padding: 0; grid-column: 1 / -1; }
659
- .topbar h1 { font-size: 22px; line-height: 28px; }
660
- .masthead { display: none; }
661
- .tabbar { display: none; }
662
- .footer { grid-column: 1 / -1; padding: 0 4px; }
663
-
664
- /* --- desktop dashboard: 12 col x 5 rows --- */
665
- .desk {
666
- display: grid;
667
- grid-column: 1 / -1;
668
- grid-template-columns: repeat(12, minmax(0, 1fr));
669
- grid-template-rows: 208px 64px 176px minmax(200px, auto) minmax(120px, auto);
670
- gap: 12px;
933
+ position: fixed;
934
+ left: var(--sp-3);
935
+ right: var(--sp-3);
936
+ bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
937
+ z-index: 30;
938
+ gap: var(--sp-1);
939
+ padding: var(--sp-2);
940
+ border-radius: var(--r-card);
941
+ background: var(--card);
942
+ box-shadow: 8px 8px 16px var(--shadow-dark), -8px -8px 16px var(--shadow-light);
671
943
  }
672
- .desk-card {
673
- position: relative;
944
+ .tab-item {
945
+ flex: 1;
674
946
  min-width: 0;
675
- padding: 20px;
676
- border-radius: 32px;
677
- overflow: hidden;
678
- }
679
- .desk-card-head {
680
- display: flex;
681
- align-items: baseline;
682
- justify-content: space-between;
683
- gap: 8px;
684
- margin-bottom: 10px;
685
- }
686
- .desk-card-head h2 { margin: 0; font-size: 15px; line-height: 24px; font-weight: 600; }
687
- .desk-status, .desk-seg, .desk-memory, .desk-chart { grid-column: span 6; }
688
- .desk-metric, .desk-switch, .desk-tile { grid-column: span 3; }
689
- .desk-stat { grid-column: span 4; }
690
-
691
- .desk-status { display: flex; align-items: center; gap: 20px; }
692
- .desk-orb { width: 88px; height: 88px; flex: 0 0 88px; display: grid; place-items: center; }
693
- .desk-status-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
694
- .desk-status-body h2 { margin: 0; font-size: 22px; line-height: 28px; font-weight: 600; }
695
- .desk-status-body .motivation { margin: 0; color: var(--text-2); font-size: 15px; line-height: 22px; }
696
-
697
- .desk-metric { display: flex; flex-direction: column; justify-content: center; gap: 10px; }
698
- .desk-metric-head {
699
- display: flex;
700
- align-items: baseline;
701
- justify-content: space-between;
702
- gap: 8px;
703
- color: var(--text-2);
704
- font-size: 13px;
705
- line-height: 18px;
706
- }
707
- .desk-metric-value { display: flex; align-items: baseline; gap: 10px; }
708
- .desk-metric-value strong {
709
- font-size: 40px;
710
- line-height: 44px;
711
- font-weight: 700;
712
- letter-spacing: -0.02em;
713
- font-variant-numeric: tabular-nums;
714
- }
715
- .desk-metric-value .sub-status { margin-left: auto; color: var(--text-2); font-size: 13px; }
716
-
717
- .desk-seg { display: flex; align-items: center; gap: 6px; padding: 6px; border-radius: 32px; background: var(--tone); box-shadow: none; }
718
- .seg-item {
719
- flex: 1 1 0;
720
- height: 52px;
721
- border: 0;
722
- border-radius: 16px;
723
- background: transparent;
724
- color: var(--text-2);
725
- font: inherit;
726
- font-size: 14px;
727
- cursor: pointer;
728
- transition: background 160ms ease, color 160ms ease;
729
- }
730
- .seg-item:hover { background: rgba(255, 255, 255, 0.04); color: var(--text); }
731
- .seg-item.active { background: var(--accent); color: #ffffff; }
732
-
733
- .desk-switch { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
734
- .desk-switch-label { font-size: 15px; line-height: 24px; font-weight: 600; }
735
- .desk-switch-control { display: flex; align-items: center; gap: 8px; }
736
- .desk-switch-control input { width: 22px; height: 22px; accent-color: var(--accent); }
737
- .desk-switch-state { color: var(--text-3); font-size: 12px; line-height: 16px; }
738
-
739
- .desk-tile { display: flex; flex-direction: column; justify-content: center; gap: 8px; }
740
- .desk-tile-head {
741
947
  display: flex;
948
+ flex-direction: column;
742
949
  align-items: center;
743
- justify-content: space-between;
744
- gap: 8px;
745
- color: var(--text-2);
746
- font-size: 12px;
950
+ gap: 2px;
951
+ padding: var(--sp-2) 0;
952
+ border-radius: var(--r-inner);
953
+ color: var(--ink-2);
954
+ font-size: var(--fs-xs);
747
955
  line-height: 16px;
956
+ transition: box-shadow var(--t), color var(--t);
748
957
  }
749
- .desk-tile strong {
750
- font-size: 22px;
751
- line-height: 28px;
752
- font-weight: 600;
753
- letter-spacing: -0.01em;
754
- overflow: hidden;
755
- text-overflow: ellipsis;
756
- white-space: nowrap;
757
- }
758
- .desk-tile-note { color: var(--text-3); font-size: 12px; line-height: 16px; }
759
- .desk-tile-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; color: var(--text-2); font-size: 13px; line-height: 18px; }
760
- .desk-tile-row b { color: var(--text); font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
761
- .desk-chevron { color: var(--text-3); font-size: 14px; }
762
- .desk-copy {
763
- height: 24px;
764
- padding: 0 10px;
765
- border: 0;
766
- border-radius: 8px;
767
- background: var(--block);
768
- color: var(--text-2);
769
- font: inherit;
770
- font-size: 12px;
771
- cursor: pointer;
772
- }
958
+ .tab-item .ico { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
959
+ .tab-item.active { color: var(--accent-ink); background: var(--card); box-shadow: var(--sink-sm); }
960
+ .tab-item.active .ico { color: var(--accent); }
961
+ .layout-toast { bottom: calc(92px + env(safe-area-inset-bottom, 0px)); }
962
+ }
773
963
 
774
- .desk-memory { display: flex; flex-direction: column; }
775
- .desk-memory .memory-list { max-height: none; }
776
- .desk-chart { display: flex; flex-direction: column; }
777
- #deskChart { width: 100%; height: 100%; min-height: 110px; display: block; }
964
+ @media (max-width: 359px) {
965
+ .tab-item span { display: none; }
966
+ .tab-item { padding: var(--sp-2) 0; }
967
+ }
778
968
 
779
- .desk-stat { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
780
- .desk-stat-row {
781
- display: flex;
782
- align-items: baseline;
783
- justify-content: space-between;
784
- gap: 8px;
785
- color: var(--text-2);
786
- font-size: 13px;
787
- line-height: 18px;
788
- }
789
- .desk-stat-row b { color: var(--text); font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
790
-
791
- /* --- tab switching on desktop --- */
792
- .panel.tab-dashboard #cards { display: none; }
793
- .panel:not(.tab-dashboard) .desk { display: none; }
794
- .panel:not(.tab-dashboard) #cards {
795
- display: grid;
796
- grid-column: 1 / -1;
797
- grid-template-columns: repeat(12, minmax(0, 1fr));
798
- gap: 12px;
799
- }
800
- .panel:not(.tab-dashboard) #cards { align-content: start; }
801
- .panel:not(.tab-dashboard) #cards > * { grid-column: span 6; }
802
- .panel:not(.tab-dashboard) #cards > [data-card-id="metrics"] { grid-column: span 8; }
803
- .panel:not(.tab-dashboard) #cards > [data-card-id="trace"] { grid-column: span 8; }
804
- .panel:not(.tab-dashboard) #cards > [data-card-id="runtime"] { grid-column: span 4; }
805
- .panel:not(.tab-dashboard) #cards > [data-card-id="model"] { grid-column: span 12; }
806
- .panel:not(.tab-dashboard) #cards > .channels-wrap { grid-column: span 12; }
807
- .panel:not(.tab-dashboard) .channels-wrap .channel-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
808
- .panel:not(.tab-dashboard) .add-cards { grid-column: 1 / -1; }
809
- .layout-editing #cards { display: grid; grid-column: 1 / -1; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 12px; }
810
- .layout-editing #cards > * { grid-column: span 6; }
811
-
812
- /* --- desktop edit mode (hide chips on desk cards) --- */
813
- .desk-hide {
814
- display: none;
815
- position: absolute;
816
- top: -8px;
817
- right: -8px;
818
- z-index: 3;
819
- place-items: center;
820
- width: 28px;
821
- height: 28px;
822
- padding: 0;
823
- border: 0;
824
- border-radius: 50%;
825
- background: var(--danger);
826
- color: #ffffff;
827
- font-size: 18px;
828
- line-height: 1;
829
- cursor: pointer;
969
+ @media (prefers-reduced-motion: reduce) {
970
+ *, *::before, *::after {
971
+ animation-duration: .001ms !important;
972
+ animation-iteration-count: 1 !important;
973
+ transition-duration: .001ms !important;
830
974
  }
831
- .layout-editing .desk-hide { display: grid; }
832
- .desk-card.is-desk-hidden { display: none !important; }
833
975
  }