principles-disciple 1.72.0 → 1.74.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 (319) hide show
  1. package/INSTALL.md +1 -3
  2. package/openclaw.plugin.json +10 -5
  3. package/package.json +17 -19
  4. package/scripts/acceptance-test.mjs +16 -73
  5. package/scripts/sync-plugin.mjs +382 -77
  6. package/src/commands/archive-impl.ts +2 -1
  7. package/src/commands/capabilities.ts +2 -2
  8. package/src/commands/context.ts +2 -2
  9. package/src/commands/disable-impl.ts +2 -1
  10. package/src/commands/evolution-status.ts +16 -16
  11. package/src/commands/export.ts +12 -67
  12. package/src/commands/pain.ts +91 -1
  13. package/src/commands/principle-rollback.ts +2 -1
  14. package/src/commands/promote-impl.ts +7 -43
  15. package/src/commands/rollback-impl.ts +2 -1
  16. package/src/commands/rollback.ts +2 -1
  17. package/src/commands/samples.ts +2 -1
  18. package/src/commands/thinking-os.ts +2 -1
  19. package/src/config/errors.ts +18 -2
  20. package/src/constants/diagnostician.ts +2 -2
  21. package/src/constants/tools.ts +2 -1
  22. package/src/core/__tests__/focus-history.test.ts +210 -0
  23. package/src/core/config.ts +1 -1
  24. package/src/core/correction-cue-learner.ts +2 -136
  25. package/src/core/correction-types.ts +16 -88
  26. package/src/core/dictionary.ts +19 -20
  27. package/src/core/empathy-keyword-matcher.ts +17 -289
  28. package/src/core/empathy-types.ts +18 -229
  29. package/src/core/event-log.ts +29 -132
  30. package/src/core/evolution-reducer.ts +21 -2
  31. package/src/core/evolution-types.ts +76 -464
  32. package/src/core/file-store.ts +80 -0
  33. package/src/core/focus-history.ts +228 -955
  34. package/src/core/local-worker-routing.ts +34 -314
  35. package/src/core/merge-gate-audit.ts +0 -195
  36. package/src/core/migration.ts +0 -1
  37. package/src/core/pain-diagnostic-gate.ts +154 -0
  38. package/src/core/pain-signal.ts +21 -138
  39. package/src/core/pain.ts +15 -88
  40. package/src/core/path-resolver.ts +0 -1
  41. package/src/core/paths.ts +0 -1
  42. package/src/core/pd-task-reconciler.ts +26 -115
  43. package/src/core/pd-task-service.ts +9 -9
  44. package/src/core/pd-task-types.ts +23 -127
  45. package/src/core/principle-compiler/__tests__/compiler-replay-gate.test.ts +174 -0
  46. package/src/core/principle-compiler/code-validator.ts +15 -42
  47. package/src/core/principle-compiler/compiler.ts +100 -15
  48. package/src/core/principle-compiler/index.ts +5 -2
  49. package/src/core/principle-compiler/template-generator.ts +4 -104
  50. package/src/core/principle-injection.ts +10 -202
  51. package/src/core/principle-internalization/filesystem-lifecycle-datasource.ts +42 -0
  52. package/src/core/principle-internalization/lifecycle-read-model.ts +39 -242
  53. package/src/core/principle-internalization/principle-lifecycle-service.ts +12 -10
  54. package/src/core/principle-tree-ledger-adapter.ts +145 -0
  55. package/src/core/principle-tree-ledger.ts +8 -6
  56. package/src/core/reflection/reflection-context.ts +14 -109
  57. package/src/core/replay-engine.ts +8 -500
  58. package/src/core/rule-host-helpers.ts +5 -35
  59. package/src/core/rule-host-types.ts +10 -82
  60. package/src/core/rule-host.ts +6 -63
  61. package/src/core/runtime-v2-prompt-activation-reader.ts +231 -0
  62. package/src/core/session-tracker.ts +87 -101
  63. package/src/core/shadow-observation-registry.ts +19 -48
  64. package/src/core/trajectory.ts +3 -1
  65. package/src/core/workflow-funnel-loader.ts +62 -68
  66. package/src/core/workspace-context.ts +46 -0
  67. package/src/core/workspace-dir-service.ts +1 -1
  68. package/src/core/workspace-dir-validation.ts +18 -9
  69. package/src/hooks/AGENTS.md +1 -1
  70. package/src/hooks/gate-block-helper.ts +71 -64
  71. package/src/hooks/gate.ts +183 -31
  72. package/src/hooks/lifecycle.ts +30 -32
  73. package/src/hooks/llm.ts +60 -32
  74. package/src/hooks/pain.ts +297 -103
  75. package/src/hooks/prompt.ts +400 -440
  76. package/src/hooks/subagent.ts +2 -29
  77. package/src/i18n/commands.ts +2 -10
  78. package/src/index.ts +95 -85
  79. package/src/openclaw-sdk.ts +311 -0
  80. package/src/service/central-database.ts +8 -4
  81. package/src/service/evolution-queue-migration.ts +2 -1
  82. package/src/service/evolution-worker.ts +163 -1786
  83. package/src/service/internalization-trigger-adapter.ts +302 -0
  84. package/src/service/keyword-optimization-service.ts +4 -4
  85. package/src/service/monitoring-query-service.ts +1 -215
  86. package/src/service/queue-io.ts +60 -331
  87. package/src/service/runtime-summary-service.ts +59 -16
  88. package/src/service/subagent-workflow/index.ts +0 -41
  89. package/src/service/subagent-workflow/types.ts +9 -120
  90. package/src/service/subagent-workflow/workflow-store.ts +2 -119
  91. package/src/service/workflow-watchdog.ts +0 -43
  92. package/src/types/event-payload.ts +16 -74
  93. package/src/types/event-types.ts +38 -547
  94. package/src/types/hygiene-types.ts +7 -30
  95. package/src/types/principle-tree-schema.ts +20 -222
  96. package/src/types/queue.ts +15 -70
  97. package/src/types/runtime-summary.ts +5 -49
  98. package/src/utils/io.ts +8 -20
  99. package/src/utils/retry.ts +1 -1
  100. package/src/utils/shadow-fingerprint.ts +2 -2
  101. package/src/utils/workspace-resolver.ts +50 -0
  102. package/templates/langs/en/core/AGENTS.md +7 -7
  103. package/templates/langs/en/core/BOOT.md +1 -1
  104. package/templates/langs/en/core/HEARTBEAT.md +2 -2
  105. package/templates/langs/en/principles/THINKING_OS.md +3 -2
  106. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  107. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  108. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  109. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  110. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  111. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  112. package/templates/langs/en/skills/evolve-task/SKILL.md +3 -3
  113. package/templates/langs/en/skills/pd-cli-operator/SKILL.md +67 -0
  114. package/templates/langs/en/skills/pd-diagnostician/SKILL.md +1 -1
  115. package/templates/langs/en/skills/pd-mentor/SKILL.md +2 -3
  116. package/templates/langs/en/skills/pd-pain-signal/SKILL.md +17 -39
  117. package/templates/langs/en/skills/pd-runtime-v2/SKILL.md +61 -0
  118. package/templates/langs/zh/core/AGENTS.md +7 -7
  119. package/templates/langs/zh/core/BOOT.md +1 -1
  120. package/templates/langs/zh/core/HEARTBEAT.md +2 -2
  121. package/templates/langs/zh/principles/THINKING_OS.md +3 -2
  122. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
  123. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
  124. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
  125. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +8 -8
  126. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
  127. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
  128. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
  129. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +21 -5
  130. package/templates/langs/zh/skills/evolve-task/SKILL.md +4 -4
  131. package/templates/langs/zh/skills/pd-cli-operator/SKILL.md +67 -0
  132. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +1 -1
  133. package/templates/langs/zh/skills/pd-mentor/SKILL.md +2 -3
  134. package/templates/langs/zh/skills/pd-pain-signal/SKILL.md +17 -38
  135. package/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +61 -0
  136. package/tests/build-artifacts.test.ts +1 -3
  137. package/tests/commands/evolution-status.test.ts +0 -118
  138. package/tests/core/bootstrap-rules.test.ts +1 -1
  139. package/tests/core/config.test.ts +1 -1
  140. package/tests/core/event-log.test.ts +35 -0
  141. package/tests/core/evolution-engine.test.ts +610 -0
  142. package/tests/core/file-store.test.ts +102 -0
  143. package/tests/core/focus-history.test.ts +203 -11
  144. package/tests/core/merge-gate-audit.test.ts +2 -169
  145. package/tests/core/migration.test.ts +7 -7
  146. package/tests/core/model-deployment-registry.test.ts +7 -1
  147. package/tests/core/model-training-registry.test.ts +19 -0
  148. package/tests/core/observability.test.ts +0 -1
  149. package/tests/core/pain-diagnostic-gate.test.ts +498 -0
  150. package/tests/core/pain.test.ts +0 -1
  151. package/tests/core/path-resolver.test.ts +1 -1
  152. package/tests/core/paths-refactor.test.ts +0 -22
  153. package/tests/core/principle-internalization/deprecated-readiness.test.ts +2 -2
  154. package/tests/core/principle-internalization/lifecycle-metrics.test.ts +2 -2
  155. package/tests/core/principle-internalization/{internalization-routing-policy.test.ts → lifecycle-routing-policy.test.ts} +6 -6
  156. package/tests/core/principle-internalization/lineage-source-retired.test.ts +56 -0
  157. package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +1 -23
  158. package/tests/core/principle-tree-ledger-adapter.test.ts +253 -0
  159. package/tests/core/reflection-context.test.ts +0 -14
  160. package/tests/core/replay-engine.test.ts +127 -215
  161. package/tests/core/rule-host-helpers.test.ts +2 -2
  162. package/tests/core/rule-implementation-runtime.test.ts +0 -27
  163. package/tests/core/workflow-funnel-loader.test.ts +162 -0
  164. package/tests/core/workspace-context.test.ts +2 -2
  165. package/tests/core/workspace-dir-validation.test.ts +8 -1
  166. package/tests/core-anti-growth.test.ts +191 -0
  167. package/tests/hook-workspace-nextaction-contract.test.ts +42 -0
  168. package/tests/hooks/confirm-first-removal.test.ts +188 -0
  169. package/tests/hooks/gate-auto-correct-shadow.test.ts +310 -0
  170. package/tests/hooks/gate-auto-correct.test.ts +665 -0
  171. package/tests/hooks/gate-no-path-write-tool.test.ts +172 -0
  172. package/tests/hooks/gate-rule-host-pipeline.test.ts +2 -1
  173. package/tests/hooks/pain.test.ts +269 -12
  174. package/tests/hooks/prompt-characterization.test.ts +500 -0
  175. package/tests/hooks/prompt-size-guard.test.ts +32 -17
  176. package/tests/hooks/runtime-v2-prompt-activation.test.ts +869 -0
  177. package/tests/index.test.ts +94 -1
  178. package/tests/integration/auto-entry-gate.test.ts +248 -0
  179. package/tests/integration/internalization-trigger-guard.test.ts +69 -0
  180. package/tests/integration/m8-legacy-paths.test.ts +63 -0
  181. package/tests/integration/runtime-v2-pain-guard.test.ts +125 -0
  182. package/tests/plugin-config-resolution-cutover.test.ts +359 -0
  183. package/tests/runtime-v2-discovery-guard.test.ts +154 -0
  184. package/tests/service/central-database.test.ts +457 -0
  185. package/tests/service/evolution-worker.correction-observer.test.ts +173 -0
  186. package/tests/service/evolution-worker.timeout.test.ts +11 -129
  187. package/tests/service/internalization-trigger-adapter.test.ts +251 -0
  188. package/tests/service/monitoring-query-service.test.ts +1 -47
  189. package/tests/service/queue-io.test.ts +1 -62
  190. package/tests/service/runtime-summary-service.test.ts +3 -1
  191. package/tests/service/workflow-watchdog.test.ts +0 -91
  192. package/tests/utils/file-lock.test.ts +5 -3
  193. package/tests/utils/session-key.test.ts +52 -0
  194. package/tests/utils/subagent-probe.test.ts +48 -1
  195. package/vitest.config.ts +4 -11
  196. package/.planning/codebase/ARCHITECTURE.md +0 -157
  197. package/.planning/codebase/CONCERNS.md +0 -145
  198. package/.planning/codebase/CONVENTIONS.md +0 -148
  199. package/.planning/codebase/INTEGRATIONS.md +0 -81
  200. package/.planning/codebase/STACK.md +0 -87
  201. package/.planning/codebase/STRUCTURE.md +0 -193
  202. package/.planning/codebase/TESTING.md +0 -243
  203. package/.planning/phases/01-basic-visualization/01-GAP-CLOSURE-VERIFICATION.md +0 -113
  204. package/docs/COMMAND_REFERENCE.md +0 -76
  205. package/docs/COMMAND_REFERENCE_EN.md +0 -79
  206. package/scripts/build-web.mjs +0 -46
  207. package/scripts/diagnose-nocturnal.mjs +0 -537
  208. package/scripts/seed-nocturnal-scenarios.mjs +0 -384
  209. package/src/commands/nocturnal-review.ts +0 -322
  210. package/src/commands/nocturnal-rollout.ts +0 -790
  211. package/src/commands/nocturnal-train.ts +0 -986
  212. package/src/commands/pd-reflect.ts +0 -88
  213. package/src/core/adaptive-thresholds.ts +0 -478
  214. package/src/core/diagnostician-task-store.ts +0 -192
  215. package/src/core/nocturnal-arbiter.ts +0 -715
  216. package/src/core/nocturnal-artifact-lineage.ts +0 -116
  217. package/src/core/nocturnal-artificer.ts +0 -257
  218. package/src/core/nocturnal-candidate-scoring.ts +0 -530
  219. package/src/core/nocturnal-compliance.ts +0 -1146
  220. package/src/core/nocturnal-dataset.ts +0 -763
  221. package/src/core/nocturnal-executability.ts +0 -428
  222. package/src/core/nocturnal-export.ts +0 -499
  223. package/src/core/nocturnal-paths.ts +0 -240
  224. package/src/core/nocturnal-reasoning-deriver.ts +0 -343
  225. package/src/core/nocturnal-rule-implementation-validator.ts +0 -246
  226. package/src/core/nocturnal-snapshot-contract.ts +0 -99
  227. package/src/core/nocturnal-trajectory-extractor.ts +0 -512
  228. package/src/core/nocturnal-trinity-types.ts +0 -218
  229. package/src/core/nocturnal-trinity.ts +0 -2680
  230. package/src/core/principle-internalization/deprecated-readiness.ts +0 -93
  231. package/src/core/principle-internalization/internalization-routing-policy.ts +0 -208
  232. package/src/core/principle-internalization/lifecycle-metrics.ts +0 -152
  233. package/src/http/principles-console-route.ts +0 -709
  234. package/src/service/central-health-service.ts +0 -49
  235. package/src/service/central-overview-service.ts +0 -138
  236. package/src/service/control-ui-query-service.ts +0 -900
  237. package/src/service/cooldown-strategy.ts +0 -97
  238. package/src/service/evolution-pain-context.ts +0 -79
  239. package/src/service/evolution-query-service.ts +0 -407
  240. package/src/service/health-query-service.ts +0 -1038
  241. package/src/service/nocturnal-config.ts +0 -214
  242. package/src/service/nocturnal-runtime.ts +0 -734
  243. package/src/service/nocturnal-service.ts +0 -1605
  244. package/src/service/nocturnal-target-selector.ts +0 -545
  245. package/src/service/sleep-cycle.ts +0 -157
  246. package/src/service/startup-reconciler.ts +0 -112
  247. package/src/service/subagent-workflow/correction-observer-types.ts +0 -82
  248. package/src/service/subagent-workflow/correction-observer-workflow-manager.ts +0 -250
  249. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +0 -1
  250. package/src/service/subagent-workflow/dynamic-timeout.ts +0 -30
  251. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +0 -268
  252. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +0 -795
  253. package/src/service/subagent-workflow/runtime-direct-driver.ts +0 -268
  254. package/src/service/subagent-workflow/workflow-manager-base.ts +0 -580
  255. package/src/tools/write-pain-flag.ts +0 -215
  256. package/templates/langs/en/skills/plan-script/SKILL.md +0 -32
  257. package/templates/langs/zh/skills/plan-script/SKILL.md +0 -32
  258. package/tests/commands/nocturnal-review.test.ts +0 -448
  259. package/tests/commands/nocturnal-train.test.ts +0 -97
  260. package/tests/commands/pd-reflect.test.ts +0 -49
  261. package/tests/core/adaptive-thresholds.test.ts +0 -261
  262. package/tests/core/nocturnal-arbiter.test.ts +0 -559
  263. package/tests/core/nocturnal-artifact-lineage.test.ts +0 -53
  264. package/tests/core/nocturnal-artificer.test.ts +0 -241
  265. package/tests/core/nocturnal-candidate-scoring.test.ts +0 -532
  266. package/tests/core/nocturnal-compliance-p-principles.test.ts +0 -133
  267. package/tests/core/nocturnal-compliance.test.ts +0 -646
  268. package/tests/core/nocturnal-dataset.test.ts +0 -892
  269. package/tests/core/nocturnal-e2e.test.ts +0 -234
  270. package/tests/core/nocturnal-executability.test.ts +0 -357
  271. package/tests/core/nocturnal-export.test.ts +0 -517
  272. package/tests/core/nocturnal-reasoning-deriver.test.ts +0 -372
  273. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +0 -428
  274. package/tests/core/nocturnal-rule-implementation-validator.test.ts +0 -127
  275. package/tests/core/nocturnal-snapshot-contract.test.ts +0 -121
  276. package/tests/core/nocturnal-trajectory-extractor.test.ts +0 -634
  277. package/tests/core/nocturnal-trinity.test.ts +0 -2053
  278. package/tests/core/pain-auto-repair.test.ts +0 -96
  279. package/tests/core/pain-integration.test.ts +0 -510
  280. package/tests/fixtures/nocturnal-reviewed-subset.json +0 -183
  281. package/tests/http/principles-console-route.test.ts +0 -162
  282. package/tests/integration/chaos-resilience.test.ts +0 -348
  283. package/tests/integration/empathy-workflow-integration.test.ts +0 -626
  284. package/tests/integration/pain-diagnostician-loop.e2e.test.ts +0 -380
  285. package/tests/service/control-ui-query-service.test.ts +0 -121
  286. package/tests/service/cooldown-strategy.test.ts +0 -164
  287. package/tests/service/data-endpoints-regression.test.ts +0 -834
  288. package/tests/service/empathy-observer-workflow-manager.test.ts +0 -175
  289. package/tests/service/evolution-worker.nocturnal.test.ts +0 -601
  290. package/tests/service/nocturnal-runtime-hardening.test.ts +0 -118
  291. package/tests/service/nocturnal-runtime.test.ts +0 -473
  292. package/tests/service/nocturnal-service-code-candidate.test.ts +0 -330
  293. package/tests/service/nocturnal-target-selector.test.ts +0 -615
  294. package/tests/service/startup-reconciler.test.ts +0 -148
  295. package/tests/tools/write-pain-flag.test.ts +0 -358
  296. package/ui/src/App.tsx +0 -45
  297. package/ui/src/api.ts +0 -220
  298. package/ui/src/charts.tsx +0 -955
  299. package/ui/src/components/ErrorState.tsx +0 -6
  300. package/ui/src/components/Loading.tsx +0 -13
  301. package/ui/src/components/ProtectedRoute.tsx +0 -12
  302. package/ui/src/components/Shell.tsx +0 -91
  303. package/ui/src/components/WorkspaceConfig.tsx +0 -178
  304. package/ui/src/components/index.ts +0 -5
  305. package/ui/src/context/auth.tsx +0 -80
  306. package/ui/src/context/theme.tsx +0 -66
  307. package/ui/src/hooks/useAutoRefresh.ts +0 -39
  308. package/ui/src/i18n/ui.ts +0 -473
  309. package/ui/src/main.tsx +0 -16
  310. package/ui/src/pages/EvolutionPage.tsx +0 -333
  311. package/ui/src/pages/FeedbackPage.tsx +0 -138
  312. package/ui/src/pages/GateMonitorPage.tsx +0 -136
  313. package/ui/src/pages/LoginPage.tsx +0 -89
  314. package/ui/src/pages/OverviewPage.tsx +0 -599
  315. package/ui/src/pages/SamplesPage.tsx +0 -174
  316. package/ui/src/pages/ThinkingModelsPage.tsx +0 -702
  317. package/ui/src/styles.css +0 -2020
  318. package/ui/src/types.ts +0 -384
  319. package/ui/src/utils/format.ts +0 -15
package/ui/src/styles.css DELETED
@@ -1,2020 +0,0 @@
1
- /* ==========================================================================
2
- Principles Console - Design System
3
- Warm Natural × Soft UI Evolution
4
- ========================================================================== */
5
-
6
- /* Google Fonts - display=swap for non-blocking font loading */
7
- @import url('https://fonts.googleapis.com/css2?family=Calistoga&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
8
-
9
- /* ==========================================================================
10
- CSS Variables - Design Tokens
11
- ========================================================================== */
12
-
13
- :root {
14
- /* Background Layers - 暖奶油色系 */
15
- --bg-base: #FAF7F2;
16
- --bg-elevated: #FFFFFF;
17
- --bg-sunken: #F0EBE3;
18
-
19
- /* Accent - 深橄榄绿 (柔和版本) */
20
- --accent: #4A7C6F;
21
- --accent-hover: #3D6A5E;
22
- --accent-soft: rgba(74, 124, 111, 0.1);
23
- --accent-muted: rgba(74, 124, 111, 0.06);
24
-
25
- /* Earth Tones - 大地色系 */
26
- --earth-brown: #8B7355;
27
- --earth-tan: #C4A882;
28
- --earth-cream: #E8DFD0;
29
- --earth-warm: #D4C4A8;
30
-
31
- /* Text Hierarchy */
32
- --text-primary: #2D2A26;
33
- --text-secondary: #6B6560;
34
- --text-tertiary: #9A948C;
35
-
36
- /* Borders & Dividers */
37
- --border: rgba(139, 115, 85, 0.15);
38
- --border-hover: rgba(139, 115, 85, 0.25);
39
-
40
- /* Status Colors */
41
- --success: #4A7C6F;
42
- --warning: #B8860B;
43
- --error: #C45C4A;
44
- --info: #5B8BA0;
45
-
46
- /* Cards & Surfaces */
47
- --card-bg: #FFFFFF;
48
- --card-radius: 16px;
49
-
50
- /* Shadows */
51
- --shadow-sm: 0 1px 2px rgba(139, 115, 85, 0.05);
52
- --shadow-md: 0 2px 8px rgba(139, 115, 85, 0.08), 0 4px 16px rgba(139, 115, 85, 0.04);
53
- --shadow-lg: 0 4px 12px rgba(139, 115, 85, 0.12), 0 8px 24px rgba(139, 115, 85, 0.06);
54
-
55
- /* Typography */
56
- --font-display: 'Calistoga', serif;
57
- --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
58
- --font-mono: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
59
-
60
- /* Spacing */
61
- --space-1: 4px;
62
- --space-2: 8px;
63
- --space-3: 12px;
64
- --space-4: 16px;
65
- --space-5: 20px;
66
- --space-6: 24px;
67
- --space-8: 32px;
68
- --space-10: 40px;
69
- --space-12: 48px;
70
-
71
- /* Border Radius */
72
- --radius-sm: 6px;
73
- --radius-md: 8px;
74
- --radius-lg: 12px;
75
- --radius-xl: 16px;
76
- --radius-full: 9999px;
77
-
78
- /* Animation */
79
- --duration-fast: 150ms;
80
- --duration-normal: 200ms;
81
- --duration-slow: 300ms;
82
- --ease-out: cubic-bezier(0.4, 0, 0.2, 1);
83
- --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
84
- }
85
-
86
- /* ==========================================================================
87
- Dark Mode — system preference + manual toggle via [data-theme]
88
- ========================================================================== */
89
-
90
- [data-theme="dark"] {
91
- --bg-base: #1A1917;
92
- --bg-elevated: #242220;
93
- --bg-sunken: #131311;
94
- --accent: #6BA394;
95
- --accent-hover: #7DB5A8;
96
- --accent-soft: rgba(107, 163, 148, 0.15);
97
- --accent-muted: rgba(107, 163, 148, 0.08);
98
- --earth-brown: #A08E74;
99
- --earth-tan: #9A8A70;
100
- --earth-cream: #3D3830;
101
- --earth-warm: #4A4238;
102
- --text-primary: #F5F2ED;
103
- --text-secondary: #A8A29A;
104
- --text-tertiary: #706B65;
105
- --border: rgba(160, 142, 116, 0.2);
106
- --border-hover: rgba(160, 142, 116, 0.35);
107
- --card-bg: #242220;
108
- --shadow-sm: 0 1px 2px rgba(0,0,0,0.2);
109
- --shadow-md: 0 2px 8px rgba(0,0,0,0.25), 0 4px 16px rgba(0,0,0,0.12);
110
- --shadow-lg: 0 4px 12px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.15);
111
- }
112
-
113
- @media (prefers-color-scheme: dark) {
114
- :root:not([data-theme="light"]) {
115
- --bg-base: #1A1917;
116
- --bg-elevated: #242220;
117
- --bg-sunken: #131311;
118
- --accent: #6BA394;
119
- --accent-hover: #7DB5A8;
120
- --accent-soft: rgba(107, 163, 148, 0.15);
121
- --accent-muted: rgba(107, 163, 148, 0.08);
122
- --earth-brown: #A08E74;
123
- --earth-tan: #9A8A70;
124
- --earth-cream: #3D3830;
125
- --earth-warm: #4A4238;
126
- --text-primary: #F5F2ED;
127
- --text-secondary: #A8A29A;
128
- --text-tertiary: #706B65;
129
- --border: rgba(160, 142, 116, 0.2);
130
- --border-hover: rgba(160, 142, 116, 0.35);
131
- --card-bg: #242220;
132
- --shadow-sm: 0 1px 2px rgba(0,0,0,0.2);
133
- --shadow-md: 0 2px 8px rgba(0,0,0,0.25), 0 4px 16px rgba(0,0,0,0.12);
134
- --shadow-lg: 0 4px 12px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.15);
135
- }
136
-
137
- .spinner {
138
- border-color: rgba(255,255,255,0.1);
139
- border-top-color: var(--accent);
140
- }
141
-
142
- .auth-checking {
143
- background: var(--bg-base);
144
- }
145
-
146
- .auth-checking-content {
147
- color: var(--text-primary);
148
- }
149
- }
150
-
151
- /* ==========================================================================
152
- Base Styles
153
- ========================================================================== */
154
-
155
- * {
156
- box-sizing: border-box;
157
- margin: 0;
158
- padding: 0;
159
- }
160
-
161
- html {
162
- font-size: 16px;
163
- -webkit-font-smoothing: antialiased;
164
- -moz-osx-font-smoothing: grayscale;
165
- }
166
-
167
- body {
168
- font-family: var(--font-body);
169
- font-size: 15px;
170
- line-height: 1.6;
171
- color: var(--text-primary);
172
- background: var(--bg-base);
173
- min-height: 100vh;
174
- }
175
-
176
- a {
177
- color: inherit;
178
- text-decoration: none;
179
- }
180
-
181
- button {
182
- font-family: inherit;
183
- cursor: pointer;
184
- border: none;
185
- background: none;
186
- }
187
-
188
- input, select {
189
- font-family: inherit;
190
- font-size: inherit;
191
- }
192
-
193
- /* ==========================================================================
194
- App Shell Layout
195
- ========================================================================== */
196
-
197
- .app-shell {
198
- display: grid;
199
- grid-template-columns: 260px minmax(0, 1fr);
200
- min-height: 100dvh;
201
- }
202
-
203
- /* Skip to content link for keyboard accessibility */
204
- .skip-link {
205
- position: absolute;
206
- top: -40px;
207
- left: 0;
208
- background: var(--accent);
209
- color: white;
210
- padding: var(--space-2) var(--space-4);
211
- z-index: 9999;
212
- border-radius: 0 0 var(--radius-md) 0;
213
- font-size: 14px;
214
- font-weight: 500;
215
- transition: top var(--duration-fast) var(--ease-out);
216
- }
217
-
218
- .skip-link:focus {
219
- top: 0;
220
- outline: 2px solid var(--accent);
221
- outline-offset: 2px;
222
- }
223
-
224
- /* ==========================================================================
225
- Sidebar
226
- ========================================================================== */
227
-
228
- .sidebar {
229
- display: flex;
230
- flex-direction: column;
231
- padding: var(--space-6);
232
- background: var(--card-bg);
233
- border-right: 1px solid var(--border);
234
- position: sticky;
235
- top: 0;
236
- height: 100vh;
237
- overflow-y: auto;
238
- }
239
-
240
- .brand {
241
- margin-bottom: var(--space-8);
242
- }
243
-
244
- .brand-logo {
245
- display: flex;
246
- align-items: center;
247
- gap: var(--space-3);
248
- margin-bottom: var(--space-3);
249
- }
250
-
251
- .brand-logo .logo-icon {
252
- width: 40px;
253
- height: 40px;
254
- display: flex;
255
- align-items: center;
256
- justify-content: center;
257
- background: var(--accent-soft);
258
- border-radius: var(--radius-md);
259
- color: var(--accent);
260
- }
261
-
262
- .brand-logo .logo-icon svg {
263
- width: 22px;
264
- height: 22px;
265
- }
266
-
267
- .brand h1 {
268
- font-family: var(--font-display);
269
- font-size: 22px;
270
- font-weight: 400;
271
- color: var(--text-primary);
272
- margin-bottom: var(--space-1);
273
- }
274
-
275
- .brand p {
276
- font-size: 13px;
277
- color: var(--text-tertiary);
278
- }
279
-
280
- .eyebrow {
281
- display: inline-block;
282
- font-size: 11px;
283
- font-weight: 600;
284
- text-transform: uppercase;
285
- letter-spacing: 0.08em;
286
- color: var(--accent);
287
- margin-bottom: var(--space-2);
288
- }
289
-
290
- /* Navigation */
291
- .nav {
292
- display: flex;
293
- flex-direction: column;
294
- gap: var(--space-2);
295
- flex: 1;
296
- }
297
-
298
- .nav-link {
299
- display: flex;
300
- align-items: center;
301
- gap: var(--space-3);
302
- padding: var(--space-3) var(--space-4);
303
- border-radius: var(--radius-lg);
304
- color: var(--text-secondary);
305
- font-size: 14px;
306
- font-weight: 500;
307
- transition: all var(--duration-fast) var(--ease-out);
308
- position: relative;
309
- }
310
-
311
- .nav-link:hover {
312
- background: var(--accent-muted);
313
- color: var(--text-primary);
314
- }
315
-
316
- .nav-link.active {
317
- background: var(--accent-soft);
318
- color: var(--accent);
319
- }
320
-
321
- .nav-link.active::before {
322
- content: '';
323
- position: absolute;
324
- left: 0;
325
- top: 50%;
326
- transform: translateY(-50%);
327
- width: 3px;
328
- height: 20px;
329
- background: var(--accent);
330
- border-radius: 0 2px 2px 0;
331
- }
332
-
333
- .nav-icon {
334
- width: 20px;
335
- height: 20px;
336
- display: flex;
337
- align-items: center;
338
- justify-content: center;
339
- flex-shrink: 0;
340
- }
341
-
342
- .nav-icon svg {
343
- width: 18px;
344
- height: 18px;
345
- stroke-width: 1.75;
346
- }
347
-
348
- /* Sidebar Footer */
349
- .sidebar-footer {
350
- display: flex;
351
- flex-direction: column;
352
- gap: var(--space-2);
353
- padding-top: var(--space-6);
354
- border-top: 1px solid var(--border);
355
- margin-top: var(--space-6);
356
- }
357
-
358
- .export-link,
359
- .logout-button {
360
- display: flex;
361
- align-items: center;
362
- gap: var(--space-3);
363
- padding: var(--space-3) var(--space-4);
364
- border-radius: var(--radius-lg);
365
- color: var(--text-secondary);
366
- font-size: 14px;
367
- font-weight: 500;
368
- transition: all var(--duration-fast) var(--ease-out);
369
- }
370
-
371
- .export-link:hover {
372
- background: var(--accent-muted);
373
- color: var(--text-primary);
374
- }
375
-
376
- .logout-button:hover {
377
- background: rgba(196, 92, 74, 0.08);
378
- color: var(--error);
379
- }
380
-
381
- /* ==========================================================================
382
- Main Content
383
- ========================================================================== */
384
-
385
- .content {
386
- padding: var(--space-6) var(--space-8);
387
- min-height: 100vh;
388
- }
389
-
390
- .page {
391
- display: grid;
392
- gap: var(--space-6);
393
- animation: page-enter var(--duration-slow) var(--ease-out);
394
- }
395
-
396
- @keyframes page-enter {
397
- from {
398
- opacity: 0;
399
- transform: translateY(8px);
400
- }
401
- to {
402
- opacity: 1;
403
- transform: translateY(0);
404
- }
405
- }
406
-
407
- .page-header {
408
- display: flex;
409
- justify-content: space-between;
410
- align-items: flex-start;
411
- gap: var(--space-4);
412
- flex-wrap: wrap;
413
- }
414
-
415
- .page-header h2 {
416
- font-family: var(--font-display);
417
- font-size: 26px;
418
- font-weight: 400;
419
- color: var(--text-primary);
420
- margin: 0;
421
- }
422
-
423
- .page-header .meta {
424
- font-size: 13px;
425
- color: var(--text-tertiary);
426
- text-align: right;
427
- display: flex;
428
- flex-wrap: wrap;
429
- gap: var(--space-3);
430
- align-items: center;
431
- }
432
-
433
- .refresh-indicator {
434
- display: inline-flex;
435
- align-items: center;
436
- gap: 4px;
437
- color: var(--accent);
438
- font-size: 12px;
439
- animation: pulse 1.5s ease-in-out infinite;
440
- }
441
-
442
- @keyframes pulse {
443
- 0%, 100% { opacity: 1; }
444
- 50% { opacity: 0.5; }
445
- }
446
-
447
- /* ==========================================================================
448
- Grid Layouts
449
- ========================================================================== */
450
-
451
- .grid {
452
- display: grid;
453
- gap: var(--space-5);
454
- }
455
-
456
- .two-columns {
457
- grid-template-columns: repeat(2, minmax(0, 1fr));
458
- }
459
-
460
- .wide-right {
461
- grid-template-columns: minmax(300px, 1.1fr) minmax(340px, 1.3fr);
462
- }
463
-
464
- .kpi-grid {
465
- display: grid;
466
- grid-template-columns: repeat(4, minmax(0, 1fr));
467
- gap: var(--space-4);
468
- }
469
-
470
- /* ==========================================================================
471
- Panel / Card
472
- ========================================================================== */
473
-
474
- .panel {
475
- background: var(--card-bg);
476
- border: 1px solid var(--border);
477
- border-radius: var(--radius-xl);
478
- padding: var(--space-5);
479
- box-shadow: var(--shadow-md);
480
- transition: all var(--duration-normal) var(--ease-out);
481
- }
482
-
483
- .panel:hover {
484
- box-shadow: var(--shadow-lg);
485
- }
486
-
487
- .panel h3 {
488
- font-size: 16px;
489
- font-weight: 600;
490
- color: var(--text-primary);
491
- margin-bottom: var(--space-4);
492
- }
493
-
494
- .panel h4 {
495
- font-size: 13px;
496
- font-weight: 600;
497
- color: var(--text-primary);
498
- margin: var(--space-4) 0 var(--space-3);
499
- }
500
-
501
- .panel.error {
502
- background: rgba(196, 92, 74, 0.05);
503
- border-color: rgba(196, 92, 74, 0.2);
504
- color: var(--error);
505
- }
506
-
507
- /* KPI Panel */
508
- .panel.kpi {
509
- padding: var(--space-4) var(--space-5);
510
- }
511
-
512
- .panel.kpi .label {
513
- font-size: 11px;
514
- font-weight: 600;
515
- text-transform: uppercase;
516
- letter-spacing: 0.06em;
517
- color: var(--text-tertiary);
518
- margin-bottom: var(--space-2);
519
- }
520
-
521
- .panel.kpi .value {
522
- font-family: var(--font-mono);
523
- font-size: 28px;
524
- font-weight: 500;
525
- color: var(--text-primary);
526
- line-height: 1.2;
527
- }
528
-
529
- .panel.kpi .sub {
530
- font-size: 12px;
531
- color: var(--text-tertiary);
532
- margin-top: var(--space-1);
533
- }
534
-
535
- /* ==========================================================================
536
- Row Cards & List Items
537
- ========================================================================== */
538
-
539
- .trend-list,
540
- .stack,
541
- .detail-stack,
542
- .list-table {
543
- display: grid;
544
- gap: var(--space-3);
545
- }
546
-
547
- .row-card,
548
- .trend-row,
549
- .table-row {
550
- display: flex;
551
- justify-content: space-between;
552
- align-items: center;
553
- gap: var(--space-4);
554
- padding: var(--space-3) var(--space-4);
555
- border: 1px solid var(--border);
556
- border-radius: var(--radius-lg);
557
- background: var(--bg-elevated);
558
- transition: all var(--duration-fast) var(--ease-out);
559
- }
560
-
561
- .trend-row:hover,
562
- .row-card:hover,
563
- .table-row:hover {
564
- background: var(--accent-muted);
565
- border-color: var(--border-hover);
566
- }
567
-
568
- .table-row {
569
- width: 100%;
570
- text-align: left;
571
- cursor: pointer;
572
- }
573
-
574
- .table-row.active {
575
- background: var(--accent-soft);
576
- border-color: var(--accent);
577
- }
578
-
579
- .row-card > div {
580
- display: flex;
581
- flex-direction: column;
582
- gap: var(--space-1);
583
- }
584
-
585
- .row-card strong,
586
- .table-row strong {
587
- font-size: 14px;
588
- font-weight: 600;
589
- color: var(--text-primary);
590
- }
591
-
592
- .row-card span,
593
- .table-row span,
594
- .trend-row span {
595
- font-size: 13px;
596
- color: var(--text-tertiary);
597
- }
598
-
599
- .row-card.vertical {
600
- display: grid;
601
- gap: var(--space-2);
602
- }
603
-
604
- .align-right {
605
- text-align: right;
606
- }
607
-
608
- /* ==========================================================================
609
- Badges & Pills
610
- ========================================================================== */
611
-
612
- .badge {
613
- display: inline-flex;
614
- align-items: center;
615
- gap: var(--space-1);
616
- padding: var(--space-1) var(--space-3);
617
- border-radius: var(--radius-full);
618
- background: var(--accent-soft);
619
- color: var(--accent);
620
- font-size: 12px;
621
- font-weight: 500;
622
- white-space: nowrap;
623
- }
624
-
625
- .badge.success {
626
- background: rgba(74, 124, 111, 0.12);
627
- color: var(--success);
628
- }
629
-
630
- .badge.warning {
631
- background: rgba(184, 134, 11, 0.12);
632
- color: var(--warning);
633
- }
634
-
635
- .badge.error {
636
- background: rgba(196, 92, 74, 0.12);
637
- color: var(--error);
638
- }
639
-
640
- .badge.info {
641
- background: rgba(91, 139, 160, 0.12);
642
- color: var(--info);
643
- }
644
-
645
- .pill-row {
646
- display: flex;
647
- flex-wrap: wrap;
648
- gap: var(--space-2);
649
- }
650
-
651
- /* ==========================================================================
652
- Buttons
653
- ========================================================================== */
654
-
655
- button,
656
- .button {
657
- display: inline-flex;
658
- align-items: center;
659
- justify-content: center;
660
- gap: var(--space-2);
661
- padding: var(--space-3) var(--space-5);
662
- border-radius: var(--radius-md);
663
- font-size: 14px;
664
- font-weight: 500;
665
- transition: all var(--duration-fast) var(--ease-out);
666
- }
667
-
668
- .button-primary {
669
- background: var(--accent);
670
- color: white;
671
- border: none;
672
- }
673
-
674
- .button-primary:hover {
675
- background: var(--accent-hover);
676
- box-shadow: var(--shadow-lg);
677
- }
678
-
679
- .button-secondary {
680
- background: transparent;
681
- color: var(--text-primary);
682
- border: 1px solid var(--border);
683
- }
684
-
685
- .button-secondary:hover {
686
- background: var(--bg-sunken);
687
- border-color: var(--border-hover);
688
- }
689
-
690
- .button-ghost {
691
- background: transparent;
692
- color: var(--text-secondary);
693
- border: none;
694
- }
695
-
696
- .button-ghost:hover {
697
- background: var(--accent-muted);
698
- color: var(--text-primary);
699
- }
700
-
701
- button:disabled {
702
- opacity: 0.5;
703
- cursor: not-allowed;
704
- }
705
-
706
- button:focus-visible,
707
- .nav-link:focus-visible,
708
- select:focus-visible,
709
- input:focus-visible,
710
- .table-row:focus-visible {
711
- outline: 2px solid var(--accent);
712
- outline-offset: 2px;
713
- }
714
-
715
- .button-row {
716
- display: flex;
717
- gap: var(--space-3);
718
- }
719
-
720
- /* ==========================================================================
721
- Filters & Select
722
- ========================================================================== */
723
-
724
- .filters {
725
- display: flex;
726
- flex-wrap: wrap;
727
- gap: var(--space-3);
728
- margin-bottom: var(--space-4);
729
- }
730
-
731
- .filters label {
732
- display: flex;
733
- align-items: center;
734
- gap: var(--space-2);
735
- font-size: 13px;
736
- color: var(--text-secondary);
737
- }
738
-
739
- select {
740
- padding: var(--space-2) var(--space-3);
741
- border: 1px solid var(--border);
742
- border-radius: var(--radius-md);
743
- background: var(--bg-elevated);
744
- color: var(--text-primary);
745
- font-size: 13px;
746
- cursor: pointer;
747
- transition: border-color var(--duration-fast) var(--ease-out);
748
- }
749
-
750
- select:hover {
751
- border-color: var(--border-hover);
752
- }
753
-
754
- select:focus {
755
- outline: none;
756
- border-color: var(--accent);
757
- box-shadow: 0 0 0 3px var(--accent-soft);
758
- }
759
-
760
- /* ==========================================================================
761
- Timeline
762
- ========================================================================== */
763
-
764
- .timeline {
765
- position: relative;
766
- padding-left: var(--space-8);
767
- }
768
-
769
- .timeline::before {
770
- content: '';
771
- position: absolute;
772
- left: 11px;
773
- top: 16px;
774
- bottom: 16px;
775
- width: 2px;
776
- background: var(--border);
777
- border-radius: 1px;
778
- }
779
-
780
- .timeline-item {
781
- position: relative;
782
- padding: var(--space-3) 0 var(--space-3) 28px;
783
- display: grid;
784
- gap: var(--space-1);
785
- }
786
-
787
- .timeline-marker {
788
- position: absolute;
789
- left: 5px;
790
- top: 16px;
791
- width: 12px;
792
- height: 12px;
793
- border-radius: 50%;
794
- border: 3px solid white;
795
- box-shadow: var(--shadow-sm);
796
- z-index: 1;
797
- }
798
-
799
- .timeline-time {
800
- font-size: 12px;
801
- font-family: var(--font-mono);
802
- color: var(--text-tertiary);
803
- }
804
-
805
- .timeline-stage {
806
- font-weight: 600;
807
- font-size: 14px;
808
- }
809
-
810
- .timeline-summary {
811
- font-size: 13px;
812
- color: var(--text-secondary);
813
- line-height: 1.5;
814
- }
815
-
816
- /* ==========================================================================
817
- Detail Panel
818
- ========================================================================== */
819
-
820
- .detail-header {
821
- display: flex;
822
- justify-content: space-between;
823
- align-items: flex-start;
824
- gap: var(--space-4);
825
- margin-bottom: var(--space-5);
826
- padding-bottom: var(--space-4);
827
- border-bottom: 1px solid var(--border);
828
- }
829
-
830
- .detail-header h3 {
831
- font-size: 18px;
832
- font-weight: 600;
833
- margin: 0;
834
- }
835
-
836
- .detail-header p {
837
- font-size: 13px;
838
- color: var(--text-tertiary);
839
- margin: var(--space-1) 0 0;
840
- }
841
-
842
- .detail-stack {
843
- display: grid;
844
- gap: var(--space-4);
845
- }
846
-
847
- .detail-stack article {
848
- padding-top: var(--space-4);
849
- border-top: 1px solid var(--border);
850
- }
851
-
852
- .detail-stack article:first-child {
853
- padding-top: 0;
854
- border-top: none;
855
- }
856
-
857
- /* ==========================================================================
858
- Forms & Inputs
859
- ========================================================================== */
860
-
861
- .form-group {
862
- display: grid;
863
- gap: var(--space-2);
864
- }
865
-
866
- .form-group label {
867
- font-size: 14px;
868
- font-weight: 500;
869
- color: var(--text-primary);
870
- }
871
-
872
- .form-group input {
873
- padding: var(--space-3) var(--space-4);
874
- border: 1px solid var(--border);
875
- border-radius: var(--radius-md);
876
- font-size: 15px;
877
- background: var(--bg-elevated);
878
- color: var(--text-primary);
879
- transition: all var(--duration-fast) var(--ease-out);
880
- }
881
-
882
- .form-group input:focus {
883
- outline: none;
884
- border-color: var(--accent);
885
- box-shadow: 0 0 0 3px var(--accent-soft);
886
- }
887
-
888
- .form-group input::placeholder {
889
- color: var(--text-tertiary);
890
- }
891
-
892
- .form-hint {
893
- font-size: 12px;
894
- color: var(--text-tertiary);
895
- }
896
-
897
- .form-hint code {
898
- font-family: var(--font-mono);
899
- font-size: 11px;
900
- background: var(--accent-soft);
901
- padding: 2px 6px;
902
- border-radius: var(--radius-sm);
903
- }
904
-
905
- .form-error {
906
- padding: var(--space-3) var(--space-4);
907
- background: rgba(196, 92, 74, 0.08);
908
- border: 1px solid rgba(196, 92, 74, 0.2);
909
- border-radius: var(--radius-md);
910
- color: var(--error);
911
- font-size: 14px;
912
- }
913
-
914
- /* ==========================================================================
915
- Auth & Login
916
- ========================================================================== */
917
-
918
- .auth-checking {
919
- min-height: 100vh;
920
- display: flex;
921
- align-items: center;
922
- justify-content: center;
923
- background: var(--bg-base);
924
- }
925
-
926
- .auth-checking-content {
927
- display: flex;
928
- flex-direction: column;
929
- align-items: center;
930
- gap: var(--space-4);
931
- color: var(--text-tertiary);
932
- }
933
-
934
- .loading-state {
935
- display: flex;
936
- flex-direction: column;
937
- align-items: center;
938
- justify-content: center;
939
- gap: var(--space-4);
940
- padding: var(--space-10);
941
- color: var(--text-tertiary);
942
- font-size: 14px;
943
- }
944
-
945
- .loading-state .spinner {
946
- width: 28px;
947
- height: 28px;
948
- }
949
-
950
- .login-page {
951
- min-height: 100vh;
952
- display: flex;
953
- align-items: center;
954
- justify-content: center;
955
- background: var(--bg-base);
956
- padding: var(--space-5);
957
- }
958
-
959
- .login-container {
960
- width: 100%;
961
- max-width: 400px;
962
- background: var(--card-bg);
963
- border: 1px solid var(--border);
964
- border-radius: var(--radius-xl);
965
- padding: var(--space-8);
966
- box-shadow: var(--shadow-lg);
967
- }
968
-
969
- .login-header {
970
- text-align: center;
971
- margin-bottom: var(--space-8);
972
- }
973
-
974
- .login-logo {
975
- display: flex;
976
- flex-direction: column;
977
- align-items: center;
978
- gap: var(--space-3);
979
- margin-bottom: var(--space-4);
980
- }
981
-
982
- .login-logo .logo-icon {
983
- width: 56px;
984
- height: 56px;
985
- display: flex;
986
- align-items: center;
987
- justify-content: center;
988
- background: var(--accent-soft);
989
- border-radius: var(--radius-lg);
990
- color: var(--accent);
991
- }
992
-
993
- .login-logo .logo-icon svg {
994
- width: 32px;
995
- height: 32px;
996
- }
997
-
998
- .login-logo h1 {
999
- font-family: var(--font-display);
1000
- font-size: 24px;
1001
- font-weight: 400;
1002
- color: var(--text-primary);
1003
- }
1004
-
1005
- .login-subtitle {
1006
- font-size: 14px;
1007
- color: var(--text-tertiary);
1008
- }
1009
-
1010
- .login-form {
1011
- display: grid;
1012
- gap: var(--space-5);
1013
- }
1014
-
1015
- .login-button {
1016
- width: 100%;
1017
- padding: var(--space-4);
1018
- background: var(--accent);
1019
- color: white;
1020
- border: none;
1021
- border-radius: var(--radius-md);
1022
- font-size: 15px;
1023
- font-weight: 500;
1024
- cursor: pointer;
1025
- transition: all var(--duration-fast) var(--ease-out);
1026
- }
1027
-
1028
- .login-button:hover:not(:disabled) {
1029
- background: var(--accent-hover);
1030
- transform: translateY(-1px);
1031
- }
1032
-
1033
- .login-button:active {
1034
- transform: scale(0.98);
1035
- }
1036
-
1037
- .login-footer {
1038
- margin-top: var(--space-6);
1039
- padding-top: var(--space-5);
1040
- border-top: 1px solid var(--border);
1041
- }
1042
-
1043
- .login-footer h4 {
1044
- font-size: 12px;
1045
- font-weight: 600;
1046
- color: var(--text-tertiary);
1047
- text-transform: uppercase;
1048
- letter-spacing: 0.05em;
1049
- margin-bottom: var(--space-3);
1050
- }
1051
-
1052
- .login-footer ol {
1053
- font-size: 13px;
1054
- color: var(--text-secondary);
1055
- line-height: 1.8;
1056
- padding-left: var(--space-5);
1057
- }
1058
-
1059
- .login-footer code {
1060
- font-family: var(--font-mono);
1061
- font-size: 11px;
1062
- background: var(--accent-soft);
1063
- padding: 2px 6px;
1064
- border-radius: var(--radius-sm);
1065
- color: var(--accent);
1066
- }
1067
-
1068
- /* ==========================================================================
1069
- Spinner
1070
- ========================================================================== */
1071
-
1072
- .spinner {
1073
- width: 32px;
1074
- height: 32px;
1075
- border: 3px solid var(--border);
1076
- border-top-color: var(--accent);
1077
- border-radius: 50%;
1078
- animation: spin 0.8s linear infinite;
1079
- }
1080
-
1081
- .spinner-small {
1082
- width: 16px;
1083
- height: 16px;
1084
- border: 2px solid rgba(255, 255, 255, 0.3);
1085
- border-top-color: white;
1086
- border-radius: 50%;
1087
- animation: spin 0.8s linear infinite;
1088
- display: inline-block;
1089
- margin-right: var(--space-2);
1090
- vertical-align: middle;
1091
- }
1092
-
1093
- @keyframes spin {
1094
- to {
1095
- transform: rotate(360deg);
1096
- }
1097
- }
1098
-
1099
- /* ==========================================================================
1100
- Pre / Code
1101
- ========================================================================== */
1102
-
1103
- pre {
1104
- font-family: var(--font-mono);
1105
- font-size: 12px;
1106
- line-height: 1.6;
1107
- white-space: pre-wrap;
1108
- overflow-wrap: anywhere;
1109
- background: var(--bg-sunken);
1110
- padding: var(--space-3) var(--space-4);
1111
- border-radius: var(--radius-md);
1112
- color: var(--text-primary);
1113
- }
1114
-
1115
- .muted {
1116
- color: var(--text-tertiary);
1117
- font-size: 13px;
1118
- }
1119
-
1120
- /* ==========================================================================
1121
- Back Button
1122
- ========================================================================== */
1123
-
1124
- .back-button {
1125
- display: flex;
1126
- align-items: center;
1127
- justify-content: center;
1128
- width: 32px;
1129
- height: 32px;
1130
- border-radius: var(--radius-md);
1131
- background: var(--bg-sunken);
1132
- color: var(--text-secondary);
1133
- transition: all var(--duration-fast) var(--ease-out);
1134
- flex-shrink: 0;
1135
- }
1136
-
1137
- .back-button:hover {
1138
- background: var(--accent-soft);
1139
- color: var(--accent);
1140
- }
1141
-
1142
- /* ==========================================================================
1143
- Empty State
1144
- ========================================================================== */
1145
-
1146
- .empty-state {
1147
- display: flex;
1148
- flex-direction: column;
1149
- align-items: center;
1150
- justify-content: center;
1151
- padding: var(--space-8) var(--space-4);
1152
- text-align: center;
1153
- color: var(--text-tertiary);
1154
- }
1155
-
1156
- .empty-state-icon {
1157
- margin-bottom: var(--space-4);
1158
- color: var(--text-tertiary);
1159
- opacity: 0.6;
1160
- }
1161
-
1162
- .empty-state-title {
1163
- font-size: 14px;
1164
- font-weight: 500;
1165
- color: var(--text-secondary);
1166
- margin-bottom: var(--space-2);
1167
- }
1168
-
1169
- .empty-state-desc {
1170
- font-size: 13px;
1171
- color: var(--text-tertiary);
1172
- max-width: 280px;
1173
- line-height: 1.5;
1174
- }
1175
-
1176
- .empty-state-action {
1177
- margin-top: var(--space-4);
1178
- }
1179
-
1180
- /* ==========================================================================
1181
- Pagination
1182
- ========================================================================== */
1183
-
1184
- .pagination {
1185
- display: flex;
1186
- justify-content: center;
1187
- align-items: center;
1188
- padding-top: var(--space-4);
1189
- font-size: 13px;
1190
- color: var(--text-tertiary);
1191
- }
1192
-
1193
- /* ==========================================================================
1194
- Responsive
1195
- ========================================================================== */
1196
-
1197
- @media (max-width: 1200px) {
1198
- .kpi-grid {
1199
- grid-template-columns: repeat(3, minmax(0, 1fr));
1200
- }
1201
- }
1202
-
1203
- @media (max-width: 1024px) {
1204
- .app-shell {
1205
- grid-template-columns: 1fr;
1206
- }
1207
-
1208
- .sidebar {
1209
- position: relative;
1210
- height: auto;
1211
- border-right: none;
1212
- border-bottom: 1px solid var(--border);
1213
- flex-direction: row;
1214
- flex-wrap: wrap;
1215
- padding: var(--space-4);
1216
- }
1217
-
1218
- .brand {
1219
- margin-bottom: 0;
1220
- margin-right: var(--space-6);
1221
- }
1222
-
1223
- .nav {
1224
- flex-direction: row;
1225
- flex-wrap: wrap;
1226
- gap: var(--space-2);
1227
- }
1228
-
1229
- .nav-link.active::before {
1230
- display: none;
1231
- }
1232
-
1233
- .sidebar-footer {
1234
- flex-direction: row;
1235
- margin-left: auto;
1236
- padding-top: 0;
1237
- border-top: none;
1238
- margin-top: 0;
1239
- }
1240
-
1241
- .two-columns,
1242
- .wide-right {
1243
- grid-template-columns: 1fr;
1244
- }
1245
- }
1246
-
1247
- @media (max-width: 640px) {
1248
- .content {
1249
- padding: var(--space-4);
1250
- }
1251
-
1252
- .kpi-grid {
1253
- grid-template-columns: repeat(2, minmax(0, 1fr));
1254
- }
1255
-
1256
- .page-header {
1257
- flex-direction: column;
1258
- }
1259
-
1260
- .page-header .meta {
1261
- text-align: left;
1262
- }
1263
-
1264
- .login-container {
1265
- padding: var(--space-6);
1266
- }
1267
- }
1268
-
1269
- /* Mobile: sidebar becomes a top nav bar */
1270
- @media (max-width: 768px) {
1271
- .app-shell {
1272
- grid-template-columns: 1fr;
1273
- grid-template-rows: auto 1fr;
1274
- }
1275
-
1276
- .sidebar {
1277
- position: sticky;
1278
- top: 0;
1279
- height: auto;
1280
- width: 100%;
1281
- flex-direction: row;
1282
- align-items: center;
1283
- padding: var(--space-3) var(--space-4);
1284
- border-right: none;
1285
- border-bottom: 1px solid var(--border);
1286
- z-index: 100;
1287
- overflow-x: auto;
1288
- overflow-y: visible;
1289
- }
1290
-
1291
- .brand {
1292
- display: none;
1293
- }
1294
-
1295
- .nav {
1296
- flex-direction: row;
1297
- flex: none;
1298
- gap: var(--space-1);
1299
- }
1300
-
1301
- .nav-link {
1302
- padding: var(--space-2) var(--space-3);
1303
- font-size: 13px;
1304
- white-space: nowrap;
1305
- }
1306
-
1307
- .nav-link::before {
1308
- display: none;
1309
- }
1310
-
1311
- .nav-icon svg {
1312
- width: 16px;
1313
- height: 16px;
1314
- }
1315
-
1316
- .sidebar-footer {
1317
- flex-direction: row;
1318
- padding-top: 0;
1319
- padding-left: var(--space-3);
1320
- border-top: none;
1321
- border-left: 1px solid var(--border);
1322
- margin-top: 0;
1323
- margin-left: auto;
1324
- gap: var(--space-1);
1325
- }
1326
-
1327
- .export-link span:last-child,
1328
- .logout-button span:last-child,
1329
- .theme-toggle span:last-child {
1330
- display: none;
1331
- }
1332
-
1333
- .theme-toggle {
1334
- padding: var(--space-2) var(--space-3);
1335
- }
1336
-
1337
- .content {
1338
- padding: var(--space-4);
1339
- min-height: calc(100dvh - 60px);
1340
- }
1341
- }
1342
-
1343
- /* ==========================================================================
1344
- Reduced Motion
1345
- ========================================================================== */
1346
-
1347
- @media (prefers-reduced-motion: reduce) {
1348
- *,
1349
- *::before,
1350
- *::after {
1351
- animation-duration: 0.01ms !important;
1352
- animation-iteration-count: 1 !important;
1353
- transition-duration: 0.01ms !important;
1354
- }
1355
- /* EXCEPT page transitions — keep them instant */
1356
- .page {
1357
- animation: none !important;
1358
- }
1359
- /* Keep skeleton shimmer for loading states */
1360
- .skeleton,
1361
- .skeleton::before,
1362
- .skeleton::after {
1363
- animation: none !important;
1364
- }
1365
- }
1366
-
1367
- /* ==========================================================================
1368
- Charts
1369
- ========================================================================== */
1370
-
1371
- /* Sparkline */
1372
- .sparkline {
1373
- display: inline-block;
1374
- vertical-align: middle;
1375
- }
1376
-
1377
- .sparkline-empty,
1378
- .chart-empty {
1379
- color: var(--text-tertiary);
1380
- font-size: 12px;
1381
- }
1382
-
1383
- .sparkline-animated .sparkline-line {
1384
- stroke-dasharray: 200;
1385
- stroke-dashoffset: 200;
1386
- animation: sparkline-draw 0.6s ease-out forwards;
1387
- }
1388
-
1389
- .sparkline-animated .sparkline-area {
1390
- opacity: 0;
1391
- animation: sparkline-fade 0.4s ease-out 0.3s forwards;
1392
- }
1393
-
1394
- @keyframes sparkline-draw {
1395
- to {
1396
- stroke-dashoffset: 0;
1397
- }
1398
- }
1399
-
1400
- @keyframes sparkline-fade {
1401
- to {
1402
- opacity: 1;
1403
- }
1404
- }
1405
-
1406
- /* Mini Bar Chart */
1407
- .mini-bar-chart .bar {
1408
- transition: opacity var(--duration-fast) var(--ease-out);
1409
- }
1410
-
1411
- .mini-bar-chart:hover .bar {
1412
- opacity: 0.8;
1413
- }
1414
-
1415
- .mini-bar-chart:hover .bar:hover {
1416
- opacity: 1;
1417
- }
1418
-
1419
- /* Grouped Bar Chart */
1420
- .grouped-bar-chart .bar {
1421
- transition: opacity var(--duration-fast) var(--ease-out);
1422
- }
1423
-
1424
- .grouped-bar-chart:hover .bar {
1425
- opacity: 0.8;
1426
- }
1427
-
1428
- .grouped-bar-chart:hover .bar:hover {
1429
- opacity: 1;
1430
- }
1431
-
1432
- /* Donut Chart */
1433
- .donut-chart-wrapper {
1434
- display: flex;
1435
- align-items: center;
1436
- gap: var(--space-4);
1437
- }
1438
-
1439
- .donut-chart {
1440
- flex-shrink: 0;
1441
- }
1442
-
1443
- .donut-segment {
1444
- transition: opacity var(--duration-fast) var(--ease-out);
1445
- }
1446
-
1447
- .donut-chart:hover .donut-segment {
1448
- opacity: 0.8;
1449
- }
1450
-
1451
- .donut-chart:hover .donut-segment:hover {
1452
- opacity: 1;
1453
- }
1454
-
1455
- .donut-total {
1456
- font-family: var(--font-mono);
1457
- font-size: 16px;
1458
- font-weight: 600;
1459
- fill: var(--text-primary);
1460
- }
1461
-
1462
- .donut-label {
1463
- font-size: 10px;
1464
- fill: var(--text-tertiary);
1465
- }
1466
-
1467
- .donut-legend {
1468
- display: flex;
1469
- flex-direction: column;
1470
- gap: var(--space-2);
1471
- }
1472
-
1473
- .legend-item {
1474
- display: flex;
1475
- align-items: center;
1476
- gap: var(--space-2);
1477
- font-size: 12px;
1478
- }
1479
-
1480
- .legend-color {
1481
- width: 10px;
1482
- height: 10px;
1483
- border-radius: var(--radius-sm);
1484
- flex-shrink: 0;
1485
- }
1486
-
1487
- .legend-label {
1488
- color: var(--text-secondary);
1489
- flex: 1;
1490
- }
1491
-
1492
- .legend-value {
1493
- font-family: var(--font-mono);
1494
- color: var(--text-primary);
1495
- font-weight: 500;
1496
- }
1497
-
1498
- /* Time Range Selector */
1499
- .time-range-selector {
1500
- display: inline-flex;
1501
- background: var(--bg-sunken);
1502
- border-radius: var(--radius-md);
1503
- padding: 2px;
1504
- }
1505
-
1506
- .time-range-option {
1507
- padding: var(--space-1) var(--space-3);
1508
- font-size: 12px;
1509
- font-weight: 500;
1510
- color: var(--text-secondary);
1511
- background: transparent;
1512
- border: none;
1513
- border-radius: var(--radius-sm);
1514
- cursor: pointer;
1515
- transition: all var(--duration-fast) var(--ease-out);
1516
- }
1517
-
1518
- .time-range-option:hover {
1519
- color: var(--text-primary);
1520
- }
1521
-
1522
- .time-range-option.active {
1523
- background: var(--card-bg);
1524
- color: var(--accent);
1525
- box-shadow: var(--shadow-sm);
1526
- }
1527
-
1528
- /* Stat Card */
1529
- .stat-card {
1530
- display: flex;
1531
- justify-content: space-between;
1532
- align-items: center;
1533
- padding: var(--space-4) var(--space-5);
1534
- background: var(--card-bg);
1535
- border: 1px solid var(--border);
1536
- border-radius: var(--radius-xl);
1537
- box-shadow: var(--shadow-md);
1538
- transition: all var(--duration-normal) var(--ease-out);
1539
- }
1540
-
1541
- .stat-card:hover {
1542
- box-shadow: var(--shadow-lg);
1543
- }
1544
-
1545
- .stat-content {
1546
- display: flex;
1547
- flex-direction: column;
1548
- gap: var(--space-1);
1549
- }
1550
-
1551
- .stat-label {
1552
- font-size: 11px;
1553
- font-weight: 600;
1554
- text-transform: uppercase;
1555
- letter-spacing: 0.06em;
1556
- color: var(--text-tertiary);
1557
- }
1558
-
1559
- .stat-value {
1560
- font-family: var(--font-mono);
1561
- font-size: 28px;
1562
- font-weight: 500;
1563
- color: var(--text-primary);
1564
- line-height: 1.2;
1565
- }
1566
-
1567
- .stat-trend-label {
1568
- font-size: 11px;
1569
- color: var(--text-tertiary);
1570
- }
1571
-
1572
- .stat-sparkline {
1573
- flex-shrink: 0;
1574
- }
1575
-
1576
- /* Trend Indicator */
1577
- .trend-indicator {
1578
- display: inline-flex;
1579
- align-items: center;
1580
- gap: var(--space-1);
1581
- font-size: 12px;
1582
- font-weight: 500;
1583
- }
1584
-
1585
- .trend-up {
1586
- color: var(--success);
1587
- }
1588
-
1589
- .trend-down {
1590
- color: var(--error);
1591
- }
1592
-
1593
- .trend-neutral {
1594
- color: var(--text-tertiary);
1595
- }
1596
-
1597
- .trend-percent {
1598
- font-family: var(--font-mono);
1599
- }
1600
-
1601
- /* ==========================================================================
1602
- Collapsible Panel
1603
- ========================================================================== */
1604
-
1605
- .collapsible-panel {
1606
- overflow: hidden;
1607
- }
1608
-
1609
- .collapsible-panel .panel-header {
1610
- display: flex;
1611
- justify-content: space-between;
1612
- align-items: center;
1613
- cursor: pointer;
1614
- user-select: none;
1615
- margin-bottom: 0;
1616
- padding: var(--space-5);
1617
- transition: background var(--duration-fast) var(--ease-out);
1618
- }
1619
-
1620
- .collapsible-panel .panel-header:hover {
1621
- background: var(--accent-muted);
1622
- }
1623
-
1624
- .collapsible-panel .panel-header-left {
1625
- display: flex;
1626
- align-items: center;
1627
- gap: var(--space-3);
1628
- }
1629
-
1630
- .collapsible-panel .panel-header h3 {
1631
- margin: 0;
1632
- }
1633
-
1634
- .collapse-toggle {
1635
- display: flex;
1636
- align-items: center;
1637
- justify-content: center;
1638
- width: 28px;
1639
- height: 28px;
1640
- border-radius: var(--radius-md);
1641
- background: var(--bg-sunken);
1642
- color: var(--text-secondary);
1643
- transition: all var(--duration-fast) var(--ease-out);
1644
- }
1645
-
1646
- .collapse-toggle:hover {
1647
- background: var(--accent-soft);
1648
- color: var(--accent);
1649
- }
1650
-
1651
- .collapsible-panel .panel-content {
1652
- padding: 0 var(--space-5) var(--space-5);
1653
- }
1654
-
1655
- .collapsible-panel.collapsed {
1656
- box-shadow: var(--shadow-sm);
1657
- }
1658
-
1659
- .collapsible-panel.collapsed .panel-header {
1660
- border-bottom: none;
1661
- }
1662
-
1663
- /* ========================================================================
1664
- * New Chart Components (Phase: WebUI Redesign)
1665
- * BulletChart, GaugeChart, PrincipleStack, QueueBar
1666
- * ======================================================================== */
1667
-
1668
- /* BulletChart - GFI with threshold zones */
1669
- .bullet-chart {
1670
- display: flex;
1671
- flex-direction: column;
1672
- }
1673
-
1674
- .bullet-labels {
1675
- display: flex;
1676
- justify-content: space-between;
1677
- margin-top: 2px;
1678
- font-size: 0.7rem;
1679
- color: var(--text-secondary);
1680
- user-select: none;
1681
- }
1682
-
1683
- /* GaugeChart - Trust semi-circle arc */
1684
- .gauge-chart svg text {
1685
- font-family: inherit;
1686
- }
1687
-
1688
- /* Panel header improvements */
1689
- .panel-header-left {
1690
- display: flex;
1691
- align-items: center;
1692
- gap: var(--space-2);
1693
- }
1694
-
1695
- .panel-header-left h3 {
1696
- margin: 0;
1697
- }
1698
-
1699
- /* Responsive grid for health panels */
1700
- @media (max-width: 768px) {
1701
- .grid {
1702
- grid-template-columns: 1fr !important;
1703
- }
1704
- }
1705
-
1706
- /* ==========================================================================
1707
- Thinking Models Page — New styles for v1.10 polish pass
1708
- ========================================================================== */
1709
-
1710
- /* Typography utility classes */
1711
- .text-xs { font-size: var(--text-xs, 0.65rem); }
1712
- .text-sm { font-size: var(--text-sm, 0.7rem); }
1713
- .text-base { font-size: var(--text-base, 0.75rem); }
1714
- .text-lg { font-size: var(--text-lg, 0.8rem); }
1715
- .text-xl { font-size: var(--text-xl, 0.85rem); }
1716
- .text-semibold { font-weight: 600; }
1717
- .text-error { color: var(--error); }
1718
-
1719
- /* Section title (replaces inline fontWeight + fontSize on h3/h4) */
1720
- .section-title {
1721
- font-size: var(--text-xl, 0.85rem);
1722
- font-weight: 600;
1723
- color: var(--text-primary);
1724
- margin-bottom: var(--space-2);
1725
- }
1726
-
1727
- /* Search + Sort + Filter controls */
1728
- .sort-button {
1729
- display: flex;
1730
- align-items: center;
1731
- gap: var(--space-1);
1732
- padding: 6px 10px;
1733
- border: 1px solid var(--border);
1734
- border-radius: 6px;
1735
- background: var(--bg-panel, var(--bg-elevated));
1736
- color: var(--text-secondary);
1737
- cursor: pointer;
1738
- font-size: var(--text-base);
1739
- transition: all var(--duration-fast) var(--ease-out);
1740
- }
1741
-
1742
- .sort-button:hover {
1743
- border-color: var(--border-hover);
1744
- color: var(--text-primary);
1745
- }
1746
-
1747
- .filter-button {
1748
- padding: 3px 8px;
1749
- border: 1px solid var(--border);
1750
- border-radius: 4px;
1751
- background: transparent;
1752
- color: var(--text-secondary);
1753
- cursor: pointer;
1754
- font-size: var(--text-sm);
1755
- transition: all var(--duration-fast) var(--ease-out);
1756
- }
1757
-
1758
- .filter-button:hover {
1759
- border-color: var(--border-hover);
1760
- }
1761
-
1762
- .filter-button.active {
1763
- border-color: var(--accent);
1764
- background: rgba(91, 139, 160, 0.15);
1765
- color: var(--accent);
1766
- }
1767
-
1768
- /* Compare button bar */
1769
- .compare-bar {
1770
- display: flex;
1771
- justify-content: space-between;
1772
- align-items: center;
1773
- padding: var(--space-2) var(--space-3);
1774
- margin-bottom: var(--space-2);
1775
- background: rgba(91, 139, 160, 0.08);
1776
- border-radius: 6px;
1777
- border: 1px solid var(--border);
1778
- }
1779
-
1780
- .compare-button {
1781
- display: flex;
1782
- align-items: center;
1783
- gap: var(--space-1);
1784
- padding: 4px 12px;
1785
- border: none;
1786
- border-radius: 4px;
1787
- background: var(--accent);
1788
- color: #fff;
1789
- cursor: pointer;
1790
- font-size: var(--text-base);
1791
- font-weight: 600;
1792
- transition: background var(--duration-fast) var(--ease-out);
1793
- }
1794
-
1795
- .compare-button:hover {
1796
- background: var(--accent-hover);
1797
- }
1798
-
1799
- /* Model list button (replaces inline style button) */
1800
- .model-list-button {
1801
- flex: 1;
1802
- display: flex;
1803
- justify-content: space-between;
1804
- align-items: center;
1805
- background: none;
1806
- border: none;
1807
- cursor: pointer;
1808
- padding: 0;
1809
- color: inherit;
1810
- text-align: left;
1811
- }
1812
-
1813
- .hits-count {
1814
- font-weight: 600;
1815
- font-size: var(--text-xl, 0.85rem);
1816
- }
1817
-
1818
- .scenario-ellipsis {
1819
- overflow: hidden;
1820
- text-overflow: ellipsis;
1821
- white-space: nowrap;
1822
- max-width: 180px;
1823
- display: block;
1824
- }
1825
-
1826
- /* Code blocks for trigger / anti-pattern */
1827
- .code-block {
1828
- font-size: var(--text-base);
1829
- white-space: pre-wrap;
1830
- word-break: break-word;
1831
- padding: var(--space-2) var(--space-3);
1832
- border-radius: 6px;
1833
- display: block;
1834
- line-height: 1.5;
1835
- font-family: var(--font-mono);
1836
- }
1837
-
1838
- .code-block-trigger {
1839
- background: var(--bg-sunken);
1840
- }
1841
-
1842
- .code-block-antipattern {
1843
- background: rgba(220, 53, 69, 0.08);
1844
- color: var(--error);
1845
- }
1846
-
1847
- /* Event context helpers */
1848
- .event-context-tool {
1849
- font-size: var(--text-sm);
1850
- color: var(--text-secondary);
1851
- display: flex;
1852
- align-items: center;
1853
- gap: var(--space-1);
1854
- }
1855
-
1856
- .event-context-pain {
1857
- font-size: var(--text-sm);
1858
- color: var(--error);
1859
- display: flex;
1860
- align-items: center;
1861
- gap: var(--space-1);
1862
- }
1863
-
1864
- .event-context-principle {
1865
- font-size: var(--text-sm);
1866
- color: var(--info);
1867
- display: flex;
1868
- align-items: center;
1869
- gap: var(--space-1);
1870
- }
1871
-
1872
- .matched-pattern {
1873
- font-size: var(--text-xs);
1874
- color: var(--text-secondary);
1875
- background: var(--bg-sunken);
1876
- padding: 2px 6px;
1877
- border-radius: 3px;
1878
- font-family: var(--font-mono);
1879
- }
1880
-
1881
- .event-trigger-excerpt {
1882
- font-size: var(--text-sm);
1883
- white-space: pre-wrap;
1884
- word-break: break-word;
1885
- }
1886
-
1887
- /* Heatmap table */
1888
- .heatmap-table {
1889
- border-collapse: collapse;
1890
- width: 100%;
1891
- }
1892
-
1893
- .heatmap-header {
1894
- text-align: center;
1895
- padding: 4px 6px;
1896
- border-bottom: 1px solid var(--border);
1897
- color: var(--text-secondary);
1898
- }
1899
-
1900
- .heatmap-scenario {
1901
- font-size: var(--text-xs);
1902
- writing-mode: vertical-lr;
1903
- transform: rotate(180deg);
1904
- height: 80px;
1905
- }
1906
-
1907
- .heatmap-sticky {
1908
- position: sticky;
1909
- left: 0;
1910
- background: var(--bg-panel, var(--bg-elevated));
1911
- z-index: 1;
1912
- text-align: left;
1913
- padding: 6px 8px;
1914
- font-size: var(--text-base);
1915
- font-weight: 600;
1916
- min-width: 100px;
1917
- }
1918
-
1919
- .heatmap-model {
1920
- font-weight: 500;
1921
- font-size: var(--text-base);
1922
- padding: 4px 8px;
1923
- border-top: 1px solid var(--border);
1924
- }
1925
-
1926
- .heatmap-cell {
1927
- text-align: center;
1928
- padding: 4px 6px;
1929
- font-size: var(--text-sm);
1930
- border-top: 1px solid var(--border);
1931
- color: var(--text-primary);
1932
- }
1933
-
1934
- /* Loader spin animation (reuses existing .spinner keyframes) */
1935
- .spin {
1936
- animation: spin 0.8s linear infinite;
1937
- }
1938
-
1939
- /* Loading placeholder for empty model definitions grid */
1940
- .loading-placeholder {
1941
- display: flex;
1942
- flex-direction: column;
1943
- align-items: center;
1944
- justify-content: center;
1945
- padding: var(--space-6);
1946
- color: var(--text-secondary);
1947
- gap: var(--space-2);
1948
- }
1949
-
1950
- /* Text alignment utility */
1951
- .text-center { text-align: center; }
1952
-
1953
- /* Stage badge (EvolutionPage) */
1954
- .stage-badge {
1955
- display: inline-flex;
1956
- align-items: center;
1957
- gap: var(--space-1);
1958
- padding: var(--space-2) var(--space-4);
1959
- border-radius: var(--radius-lg);
1960
- font-size: var(--text-lg, 0.8rem);
1961
- font-weight: 600;
1962
- background: var(--accent);
1963
- color: #fff;
1964
- border: 2px solid var(--accent);
1965
- }
1966
-
1967
- .stage-badge svg {
1968
- width: 16px;
1969
- height: 16px;
1970
- }
1971
-
1972
- /* Sample pre blocks (SamplesPage) */
1973
- .sample-pre {
1974
- white-space: pre-wrap;
1975
- word-break: break-word;
1976
- background: var(--bg-sunken);
1977
- padding: var(--space-3);
1978
- border-radius: var(--radius-md);
1979
- font-family: var(--font-mono);
1980
- font-size: var(--text-sm);
1981
- overflow-x: auto;
1982
- max-width: 100%;
1983
- }
1984
-
1985
- /* GFI big number (FeedbackPage) */
1986
- .gfi-big-number {
1987
- font-size: 3rem;
1988
- font-weight: 700;
1989
- line-height: 1;
1990
- }
1991
-
1992
- /* Progress bar (shared component pattern) */
1993
- .progress-bar {
1994
- width: 100%;
1995
- height: 8px;
1996
- background: var(--bg-sunken);
1997
- border-radius: 4px;
1998
- overflow: hidden;
1999
- margin-top: var(--space-2);
2000
- }
2001
-
2002
- .progress-bar-fill {
2003
- height: 100%;
2004
- border-radius: 4px;
2005
- transition: width 0.3s ease;
2006
- }
2007
-
2008
- /* GateMonitor trust/EP big numbers */
2009
- .stat-big-number {
2010
- font-size: 1.5rem;
2011
- font-weight: 700;
2012
- line-height: 1;
2013
- }
2014
-
2015
- /* EvolutionPage icon alignment */
2016
- .panel h3 svg {
2017
- vertical-align: middle;
2018
- margin-right: var(--space-1);
2019
- }
2020
-