@azure-id/orc 1.9.1 → 2.0.2

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 (224) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/README-id.md +20 -36
  3. package/README.md +24 -34
  4. package/bin/build-agents.js +206 -109
  5. package/bin/cli.js +760 -62
  6. package/bin/gotcha-import.js +1081 -0
  7. package/bin/gotcha.js +1286 -0
  8. package/bin/graph-query.js +1 -1
  9. package/bin/graph.js +717 -717
  10. package/bin/habit.js +1453 -0
  11. package/bin/mockrun-catalog.js +281 -276
  12. package/bin/onboarding-content.js +4 -4
  13. package/bin/pricing.json +207 -200
  14. package/bin/run-undo.js +398 -0
  15. package/bin/trace-write.js +657 -0
  16. package/bin/verify-contracts.js +527 -81
  17. package/bin/verify-package.js +58 -11
  18. package/bin/webui/api.js +26 -0
  19. package/bin/webui/app.html +239 -232
  20. package/bin/webui/css/00-tokens.css +110 -92
  21. package/bin/webui/css/04-motion.css +249 -152
  22. package/bin/webui/css/06-responsive.css +203 -178
  23. package/bin/webui/css/panels/behaviour.css +205 -0
  24. package/bin/webui/css/panels/knowledge.css +563 -116
  25. package/bin/webui/fixtures/behaviour.js +532 -0
  26. package/bin/webui/fixtures/extra.js +2036 -2036
  27. package/bin/webui/fixtures/hookui.js +5 -5
  28. package/bin/webui/fixtures/index.js +34 -0
  29. package/bin/webui/fixtures/knowledge.js +7 -1
  30. package/bin/webui/fixtures/settings.js +305 -305
  31. package/bin/webui/fixtures/stats.js +16 -0
  32. package/bin/webui/i18n/en/behaviour.json +143 -0
  33. package/bin/webui/i18n/en/knowledge.json +117 -2
  34. package/bin/webui/i18n/en/nav.json +25 -24
  35. package/bin/webui/i18n/en/tour.json +37 -35
  36. package/bin/webui/i18n/id/behaviour.json +143 -0
  37. package/bin/webui/i18n/id/knowledge.json +117 -2
  38. package/bin/webui/i18n/id/nav.json +25 -24
  39. package/bin/webui/i18n/id/tour.json +37 -35
  40. package/bin/webui/js/01-i18n.js +155 -154
  41. package/bin/webui/js/90-tour.js +498 -494
  42. package/bin/webui/js/91-shortcuts.js +126 -126
  43. package/bin/webui/js/99-boot.js +121 -118
  44. package/bin/webui/js/panels/behaviour.js +1022 -0
  45. package/bin/webui/js/panels/knowledge.js +552 -7
  46. package/bin/webui/js/panels/overview.js +13 -4
  47. package/mock-run/INDEX.md +109 -107
  48. package/mock-run/context-combiner.md +100 -100
  49. package/mock-run/gotcha-import.md +118 -0
  50. package/mock-run/habits.md +129 -0
  51. package/mock-run/orc-budget.md +534 -534
  52. package/mock-run/orc-challenge-council.md +262 -262
  53. package/mock-run/orc-quick.md +6 -1
  54. package/mock-run/orc-ultra.md +103 -103
  55. package/package.json +1 -1
  56. package/templates/agents/MODEL-MAPPING.md +49 -49
  57. package/templates/agents/orc-advisor-opus-5-xhigh.md +50 -56
  58. package/templates/agents/orc-analyze-mini-opus-5-med.md +55 -60
  59. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +55 -58
  60. package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
  61. package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
  62. package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
  63. package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
  64. package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
  65. package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
  66. package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
  67. package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
  68. package/templates/agents/orc-claude-writer-opus-4-8-high.md +48 -53
  69. package/templates/agents/orc-claude-writer-opus-5-med.md +48 -55
  70. package/templates/agents/orc-context-combiner-opus-5-high.md +78 -88
  71. package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
  72. package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
  73. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  74. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  75. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  76. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  77. package/templates/agents/orc-executor-opus-5-high.md +15 -7
  78. package/templates/agents/orc-executor-opus-5-low.md +15 -7
  79. package/templates/agents/orc-executor-opus-5-med.md +15 -7
  80. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  81. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  82. package/templates/agents/orc-executor-sonnet-5-high.md +14 -6
  83. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  84. package/templates/agents/orc-judge-opus-5-xhigh.md +81 -85
  85. package/templates/agents/orc-learn-writer-opus-5-low.md +67 -73
  86. package/templates/agents/orc-pattern-codifier-opus-5-med.md +58 -65
  87. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  88. package/templates/agents/orc-planner-mini-opus-5-med.md +4 -7
  89. package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
  90. package/templates/agents/orc-planner-opus-5-med.md +157 -160
  91. package/templates/agents/orc-recon-opus-5-low.md +3 -10
  92. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  93. package/templates/agents/orc-retro-opus-5-med.md +8 -10
  94. package/templates/agents/orc-retro-sonnet-5-high.md +6 -7
  95. package/templates/agents/orc-reviewer-opus-5-med.md +96 -60
  96. package/templates/agents/orc-scout-opus-5-low.md +35 -40
  97. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  98. package/templates/agents/orc-system-analyst-opus-5-high.md +115 -120
  99. package/templates/agents/orc-test-author-opus-5-med.md +70 -71
  100. package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
  101. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
  102. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  103. package/templates/agents/orc-verifier-opus-5-med.md +77 -69
  104. package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +74 -79
  105. package/templates/agents/orc-wiki-scanner-opus-5-med.md +74 -81
  106. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  107. package/templates/commands/orc-analyze.md +13 -21
  108. package/templates/commands/orc-fast.md +10 -15
  109. package/templates/commands/orc-poly.md +12 -21
  110. package/templates/commands/orc-pr-driver.md +11 -30
  111. package/templates/commands/orc-pr-setup.md +10 -31
  112. package/templates/commands/orc-route.md +11 -41
  113. package/templates/commands/orc-test.md +5 -60
  114. package/templates/commands/orc-ultra.md +17 -17
  115. package/templates/commands/orc-verify.md +11 -11
  116. package/templates/hooks/README.md +36 -2
  117. package/templates/hooks/orc-effort-guard.js +178 -178
  118. package/templates/hooks/orc-session-hook.js +264 -0
  119. package/templates/hooks/orc-statusline.js +9 -7
  120. package/templates/skills/_shared/README.md +9 -0
  121. package/templates/skills/_shared/code-graph.md +48 -56
  122. package/templates/skills/_shared/config-precedence.md +200 -198
  123. package/templates/skills/_shared/extra-dispatch.md +1331 -1346
  124. package/templates/skills/_shared/gotchas.md +228 -177
  125. package/templates/skills/_shared/habits.md +101 -0
  126. package/templates/skills/_shared/lane-contract.md +84 -0
  127. package/templates/skills/_shared/opus5-only.md +8 -8
  128. package/templates/skills/_shared/phases/README.md +142 -83
  129. package/templates/skills/_shared/phases/analyst-gates.md +125 -136
  130. package/templates/skills/_shared/phases/execution.md +8 -14
  131. package/templates/skills/_shared/phases/house-rules.md +27 -32
  132. package/templates/skills/_shared/phases/intake.md +127 -133
  133. package/templates/skills/_shared/phases/mock-example.md +46 -56
  134. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  135. package/templates/skills/_shared/phases/planning.md +7 -17
  136. package/templates/skills/_shared/phases/preflight.md +19 -42
  137. package/templates/skills/_shared/phases/review.md +23 -27
  138. package/templates/skills/_shared/phases/rules.md +18 -42
  139. package/templates/skills/_shared/phases/scoring.md +55 -65
  140. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  141. package/templates/skills/_shared/phases/security.md +45 -55
  142. package/templates/skills/_shared/phases/ship.md +6 -15
  143. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  144. package/templates/skills/_shared/phases/summary.md +73 -48
  145. package/templates/skills/_shared/phases/testgen.md +41 -51
  146. package/templates/skills/_shared/phases/trace-verbs.md +433 -0
  147. package/templates/skills/_shared/phases/trace.md +136 -367
  148. package/templates/skills/_shared/phases/verify.md +62 -70
  149. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  150. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  151. package/templates/skills/_shared/read-ladder.md +2 -55
  152. package/templates/skills/_shared/return-validation.md +17 -70
  153. package/templates/skills/_shared/review-slice.md +79 -0
  154. package/templates/skills/_shared/smoke-gate.md +46 -28
  155. package/templates/skills/context-combiner/SKILL.md +16 -45
  156. package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
  157. package/templates/skills/orc/README.md +2 -2
  158. package/templates/skills/orc/SKILL.md +41 -69
  159. package/templates/skills/orc/config.md +9 -9
  160. package/templates/skills/orc/examples/full-run-mock.md +73 -73
  161. package/templates/skills/orc/references/effort-and-mode.md +222 -222
  162. package/templates/skills/orc/references/pattern-gate.md +89 -89
  163. package/templates/skills/orc/references/phases/intake.md +41 -47
  164. package/templates/skills/orc/references/phases/integration.md +13 -19
  165. package/templates/skills/orc/references/preflight-report.md +10 -11
  166. package/templates/skills/orc/references/ultra-mode.md +11 -9
  167. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  168. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  169. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  170. package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
  171. package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
  172. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +35 -76
  173. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  174. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  175. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +34 -45
  176. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  177. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  178. package/templates/skills/orc-advisor/SKILL.md +56 -60
  179. package/templates/skills/orc-analyze/SKILL.md +32 -68
  180. package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
  181. package/templates/skills/orc-analyze/schemas/report-audit.md +84 -83
  182. package/templates/skills/orc-analyze/schemas/report-prose.md +64 -63
  183. package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
  184. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  185. package/templates/skills/orc-challenge/README.md +142 -142
  186. package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
  187. package/templates/skills/orc-challenge/references/council.md +315 -315
  188. package/templates/skills/orc-challenge/references/intake.md +171 -171
  189. package/templates/skills/orc-claude/SKILL.md +14 -14
  190. package/templates/skills/orc-diy/README.md +174 -143
  191. package/templates/skills/orc-diy/SKILL.md +23 -74
  192. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  193. package/templates/skills/orc-diy/references/flow-schema.md +1 -1
  194. package/templates/skills/orc-doc/README.md +229 -229
  195. package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
  196. package/templates/skills/orc-doc/references/chunking.md +527 -527
  197. package/templates/skills/orc-fast/SKILL.md +45 -73
  198. package/templates/skills/orc-judge/SKILL.md +77 -82
  199. package/templates/skills/orc-learn/SKILL.md +14 -14
  200. package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
  201. package/templates/skills/orc-mini/SKILL.md +65 -113
  202. package/templates/skills/orc-pattern/SKILL.md +27 -48
  203. package/templates/skills/orc-poly/SKILL.md +32 -61
  204. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  205. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  206. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  207. package/templates/skills/orc-quick/README.md +43 -2
  208. package/templates/skills/orc-quick/SKILL.md +76 -107
  209. package/templates/skills/orc-quick/references/dispatch-gate.md +16 -5
  210. package/templates/skills/orc-quick/references/gh-mode.md +48 -1
  211. package/templates/skills/orc-quick/references/look.md +3 -1
  212. package/templates/skills/orc-retro/SKILL.md +19 -18
  213. package/templates/skills/orc-retro/examples/retro-mock.md +1 -1
  214. package/templates/skills/orc-route/SKILL.md +25 -45
  215. package/templates/skills/orc-test/SKILL.md +16 -37
  216. package/templates/skills/orc-verify/SKILL.md +21 -39
  217. package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
  218. package/templates/skills/orc-wait/SKILL.md +156 -163
  219. package/templates/skills/orc-wiki/references/extra.md +1 -1
  220. package/templates/skills/orc-wiki/references/phases/phase-0.md +1 -6
  221. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  222. package/templates/skills/orc-wiki/references/phases/phase-2.md +1 -6
  223. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  224. package/templates/skills/orc-wiki/references/phases/phase-3c.md +1 -6
@@ -1,178 +1,203 @@
1
- /* 06-responsive.css — orc ui
2
- The width breakpoints that cross panel boundaries (the rail becomes a strip,
3
- the Learn rail becomes a scrollable row). They override rules from the shell
4
- AND from four panels, so they load after every one of them — the same reason
5
- 04-motion.css is last. Breakpoints that only touch ONE panel stay in that
6
- panel's file.
7
-
8
- The <link> ORDER in app.html is the cascade order, and the numeric
9
- prefix is that order. No @import: it would carry no session token and
10
- 401. */
11
-
12
- /* --------------------------------------------------------------- RESPONSIVE */
13
-
14
- @media (max-width: 1040px) {
15
- /* The Learn rail stops being a rail and becomes a scrollable strip above the
16
- reading pane — a 244px column plus prose does not fit twice over. */
17
- .learn { grid-template-columns: 1fr; }
18
- .learn-side { position: static; max-height: none; }
19
- .learn-nav { flex-direction: row; overflow-x: auto; padding-bottom: 2px; }
20
- .learn-nav-item { flex: 0 0 auto; max-width: 210px; }
21
- }
22
-
23
- @media (max-width: 900px) {
24
- .shell { grid-template-columns: 1fr; }
25
- .rail {
26
- position: static;
27
- height: auto;
28
- flex-direction: row;
29
- align-items: center;
30
- gap: var(--sp-4);
31
- overflow-x: auto;
32
- border-right: 0;
33
- border-bottom: 1px solid var(--line-soft);
34
- }
35
- .nav { flex-direction: row; flex-wrap: nowrap; }
36
- .nav a { white-space: nowrap; }
37
- .rail-foot { flex-direction: row; align-items: center; }
38
- .rail-project { max-width: 180px; }
39
- .main { padding: var(--sp-4); }
40
- .setting { grid-template-columns: 1fr; }
41
- .setting-control { align-items: flex-start; }
42
- /* The rank ladder keeps its prio column — it is 34px and it is the thing
43
- that makes the row readable as a ladder rather than a list. The state
44
- chip wraps under instead, which is the only child that can spare the
45
- line. Declared explicitly, like every `.run-card` variant below. */
46
- .rank-row { grid-template-columns: 34px minmax(0, 1fr); }
47
- .rank-row > .chip { grid-column: 2; justify-self: start; }
48
- /* A phase row drops its right-hand column under the body rather than
49
- squeezing it: `read`, `when` and the layer list are facts, and a fact
50
- wrapped to one character per line is not readable. Declared explicitly. */
51
- .phase-row { grid-template-columns: 28px minmax(0, 1fr); }
52
- .phase-right { grid-column: 2; flex-direction: row; flex-wrap: wrap; align-items: center; }
53
- .call-detail { padding-left: var(--sp-3); }
54
- /* Every `.run-card` VARIANT collapses explicitly. A variant that inherits a
55
- column count it does not have is the v0.49.2 Overview collision again, just
56
- at a narrower width. */
57
- .run-card { grid-template-columns: 16px 80px minmax(0, 1fr); }
58
- .run-card.no-caret { grid-template-columns: 80px minmax(0, 1fr); }
59
- .run-card.has-extra { grid-template-columns: 16px 80px auto minmax(0, 1fr); }
60
- .run-card.no-caret.has-extra { grid-template-columns: 80px auto minmax(0, 1fr); }
61
- .run-age { grid-column: 3; }
62
- .run-card.no-caret .run-age { grid-column: 2; }
63
- .run-card.has-extra .run-age { grid-column: 4; }
64
- .run-card.no-caret.has-extra .run-age { grid-column: 3; }
65
- .todo { grid-template-columns: 4px minmax(0, 1fr); }
66
- .todo-cta { grid-column: 2; margin-top: var(--sp-2); }
67
- /* Extra. v0.50.0 brought the rail's segment floor down here so a band was
68
- never squeezed to a sliver. v0.53.0 deleted that floor entirely: the band
69
- ladder puts the proportional bar INSIDE a full-width row, so there is
70
- nothing left to squeeze and nothing left to tune per viewport. What the
71
- ladder does need at this width is for its head to stop pretending it has
72
- five columns. */
73
- .ex-band-head { grid-template-columns: minmax(0, 30%) minmax(0, auto) minmax(0, 1fr) 16px; }
74
- /* v0.55.0 — EVERY VARIANT COLLAPSES EXPLICITLY. A position row has no bar, so
75
- its first column is the slot name rather than a track; leaving it on the
76
- band template here would put the target under the caret. */
77
- .ex-slot-head { grid-template-columns: minmax(0, 40%) minmax(0, 1fr) 16px; }
78
- .ex-slot-when { grid-column: 1 / -1; }
79
- /* v1.5.0 — /orc-test. Every grid here DECLARES its columns, so every one of
80
- them collapses explicitly rather than inheriting a template it no longer
81
- has the width for. The route, the case row and the OWASP row all keep the
82
- SAME child count in every state (that is the `.ex-tool` lesson), so the
83
- collapse is a template change and never a hidden child. */
84
- .ts-route { grid-template-columns: 56px minmax(0, 1fr); }
85
- .ts-route > .chip { grid-column: 2; justify-self: start; }
86
- .ts-where { grid-column: 1 / -1; }
87
- .ts-case { grid-template-columns: 56px minmax(0, 1fr); }
88
- .ts-case > .chip { grid-column: 2; justify-self: start; }
89
- .ts-case-mid { grid-column: 1 / -1; }
90
- .ts-case-tail { grid-column: 1 / -1; justify-content: flex-start; }
91
- .ts-owasp { grid-template-columns: 56px minmax(0, 1fr); }
92
- .ts-owasp-mid { grid-column: 1 / -1; }
93
- .ex-band-chips { grid-column: 1 / -1; justify-content: flex-start; }
94
- .ex-route-controls { align-items: stretch; }
95
- .ex-route-controls .btn { width: 100%; }
96
- /* v0.53.0 — `.ex-tool` was the one `.ex-*` block with no entry here at all.
97
- At this width a tool card's actions are the reason you opened the panel, so
98
- they go full width rather than being squeezed onto the end of a row. */
99
- .ex-tool > .row-actions:not(:first-child) { align-items: stretch; }
100
- .ex-tool > .row-actions:not(:first-child) .btn { width: 100%; }
101
- /* v0.54.0 — a recovery row's identity is the longest thing in it, so at this
102
- width it takes its own line rather than truncating a profile and a model
103
- into nothing. The row is a FLEX COLUMN, so this is a wrap rather than a
104
- second grid template. */
105
- .ex-rec-head { flex-wrap: wrap; }
106
- .ex-rec-who { flex: 1 1 100%; white-space: normal; }
107
- }
108
-
109
- @media (max-width: 600px) {
110
- /* Below this there is no honest way to keep a chip, a slug and an age on one
111
- line, so the card stacks: chip, then the slug and where it stands, then the
112
- age. One column, in reading order. */
113
- .run-card,
114
- .run-card.no-caret,
115
- .run-card.has-extra,
116
- .run-card.no-caret.has-extra {
117
- grid-template-columns: minmax(0, 1fr);
118
- gap: var(--sp-2);
119
- }
120
- .run-caret { display: none; }
121
- .run-card .run-age { grid-column: 1; }
122
- /* Extra: the provider catalog stops being a grid — below this a two-column
123
- tile cannot hold a base URL and two links without wrapping mid-word — and
124
- the connect form's two columns become one. */
125
- .ex-provider-grid { grid-template-columns: minmax(0, 1fr); }
126
- .ex-strip { gap: var(--sp-3); }
127
- .ex-route-controls > * { flex: 1 1 100%; }
128
- /* The tool card's head stops being a row: a label, a binary name and a state
129
- chip cannot share a line honestly below this. */
130
- .ex-tool > .row-actions:first-child { flex-direction: column; align-items: flex-start; }
131
- /* A per-file position line cannot hold a path, a state word and a line delta
132
- on one row below this — and the path is the half that must stay readable. */
133
- .ex-rec-file { flex-direction: column; align-items: flex-start; }
134
-
135
- /* v1.3.0 — the CLI Hook Interface. Every variant that DECLARES columns
136
- collapses explicitly; the ones that do not (the chip, the palette row) are
137
- flex and wrap on their own, which is exactly why they were written that
138
- way. The PREVIEW never collapses: it is a monospaced grid and squeezing it
139
- would misreport the width the user is deciding. It scrolls instead. */
140
- .hk-degrade-row,
141
- .hk-compare-row,
142
- .hk-field,
143
- .hk-check {
144
- grid-template-columns: 1fr;
145
- gap: 4px;
146
- }
147
- .hk-degrade-label,
148
- .hk-compare-label {
149
- text-align: left;
150
- }
151
- .hk-gallery {
152
- grid-template-columns: 1fr 1fr;
153
- }
154
- .hk-prow-id {
155
- min-width: 0;
156
- }
157
- /* v1.4.1 — the editor's two-column field (a name plus the sentence that
158
- explains it, then the control) stacks; and DRAG IS OFF below this width. A
159
- 40-pixel drop gap on a phone is not a target, so the three buttons on every
160
- chip are the path — which is why they are buttons on the chip and not a
161
- menu behind one. */
162
- .hk-chip {
163
- max-width: none;
164
- flex-basis: 100%;
165
- cursor: default;
166
- }
167
- .hk-grip { display: none; }
168
- .hk-add { flex-basis: 100%; }
169
- .hk-picker, .hk-editor { min-width: 0; }
170
- .hk-theme { flex-basis: 100%; max-width: none; }
171
- /* The caution KEEPS its two columns. The mark and the sentence belong to each
172
- other, and stacking them puts a lone ✕ on a line of its own above the text
173
- it is about. The mark column narrows instead. */
174
- .hk-caution {
175
- grid-template-columns: 14px 1fr;
176
- gap: 6px;
177
- }
178
- }
1
+ /* 06-responsive.css — orc ui
2
+ The width breakpoints that cross panel boundaries (the rail becomes a strip,
3
+ the Learn rail becomes a scrollable row). They override rules from the shell
4
+ AND from four panels, so they load after every one of them — the same reason
5
+ 04-motion.css is last. Breakpoints that only touch ONE panel stay in that
6
+ panel's file.
7
+
8
+ The <link> ORDER in app.html is the cascade order, and the numeric
9
+ prefix is that order. No @import: it would carry no session token and
10
+ 401. */
11
+
12
+ /* --------------------------------------------------------------- RESPONSIVE */
13
+
14
+ @media (max-width: 1040px) {
15
+ /* The Learn rail stops being a rail and becomes a scrollable strip above the
16
+ reading pane — a 244px column plus prose does not fit twice over. */
17
+ .learn { grid-template-columns: 1fr; }
18
+ .learn-side { position: static; max-height: none; }
19
+ .learn-nav { flex-direction: row; overflow-x: auto; padding-bottom: 2px; }
20
+ .learn-nav-item { flex: 0 0 auto; max-width: 210px; }
21
+ }
22
+
23
+ @media (max-width: 900px) {
24
+ .shell { grid-template-columns: 1fr; }
25
+ .rail {
26
+ position: static;
27
+ height: auto;
28
+ flex-direction: row;
29
+ align-items: center;
30
+ gap: var(--sp-4);
31
+ overflow-x: auto;
32
+ border-right: 0;
33
+ border-bottom: 1px solid var(--line-soft);
34
+ }
35
+ .nav { flex-direction: row; flex-wrap: nowrap; }
36
+ .nav a { white-space: nowrap; }
37
+ .rail-foot { flex-direction: row; align-items: center; }
38
+ .rail-project { max-width: 180px; }
39
+ .main { padding: var(--sp-4); }
40
+ .setting { grid-template-columns: 1fr; }
41
+ .setting-control { align-items: flex-start; }
42
+ /* The rank ladder keeps its prio column — it is 34px and it is the thing
43
+ that makes the row readable as a ladder rather than a list. The state
44
+ chip wraps under instead, which is the only child that can spare the
45
+ line. Declared explicitly, like every `.run-card` variant below. */
46
+ .rank-row { grid-template-columns: 34px minmax(0, 1fr); }
47
+ .rank-row > .chip { grid-column: 2; justify-self: start; }
48
+ /* A phase row drops its right-hand column under the body rather than
49
+ squeezing it: `read`, `when` and the layer list are facts, and a fact
50
+ wrapped to one character per line is not readable. Declared explicitly. */
51
+ .phase-row { grid-template-columns: 28px minmax(0, 1fr); }
52
+ .phase-right { grid-column: 2; flex-direction: row; flex-wrap: wrap; align-items: center; }
53
+ .call-detail { padding-left: var(--sp-3); }
54
+ /* Every `.run-card` VARIANT collapses explicitly. A variant that inherits a
55
+ column count it does not have is the v0.49.2 Overview collision again, just
56
+ at a narrower width. */
57
+ .run-card { grid-template-columns: 16px 80px minmax(0, 1fr); }
58
+ .run-card.no-caret { grid-template-columns: 80px minmax(0, 1fr); }
59
+ .run-card.has-extra { grid-template-columns: 16px 80px auto minmax(0, 1fr); }
60
+ .run-card.no-caret.has-extra { grid-template-columns: 80px auto minmax(0, 1fr); }
61
+ .run-age { grid-column: 3; }
62
+ .run-card.no-caret .run-age { grid-column: 2; }
63
+ .run-card.has-extra .run-age { grid-column: 4; }
64
+ .run-card.no-caret.has-extra .run-age { grid-column: 3; }
65
+ .todo { grid-template-columns: 4px minmax(0, 1fr); }
66
+ .todo-cta { grid-column: 2; margin-top: var(--sp-2); }
67
+ /* Extra. v0.50.0 brought the rail's segment floor down here so a band was
68
+ never squeezed to a sliver. v0.53.0 deleted that floor entirely: the band
69
+ ladder puts the proportional bar INSIDE a full-width row, so there is
70
+ nothing left to squeeze and nothing left to tune per viewport. What the
71
+ ladder does need at this width is for its head to stop pretending it has
72
+ five columns. */
73
+ .ex-band-head { grid-template-columns: minmax(0, 30%) minmax(0, auto) minmax(0, 1fr) 16px; }
74
+ /* v0.55.0 — EVERY VARIANT COLLAPSES EXPLICITLY. A position row has no bar, so
75
+ its first column is the slot name rather than a track; leaving it on the
76
+ band template here would put the target under the caret. */
77
+ .ex-slot-head { grid-template-columns: minmax(0, 40%) minmax(0, 1fr) 16px; }
78
+ .ex-slot-when { grid-column: 1 / -1; }
79
+ /* v1.5.0 — /orc-test. Every grid here DECLARES its columns, so every one of
80
+ them collapses explicitly rather than inheriting a template it no longer
81
+ has the width for. The route, the case row and the OWASP row all keep the
82
+ SAME child count in every state (that is the `.ex-tool` lesson), so the
83
+ collapse is a template change and never a hidden child. */
84
+ .ts-route { grid-template-columns: 56px minmax(0, 1fr); }
85
+ .ts-route > .chip { grid-column: 2; justify-self: start; }
86
+ .ts-where { grid-column: 1 / -1; }
87
+ .ts-case { grid-template-columns: 56px minmax(0, 1fr); }
88
+ .ts-case > .chip { grid-column: 2; justify-self: start; }
89
+ .ts-case-mid { grid-column: 1 / -1; }
90
+ .ts-case-tail { grid-column: 1 / -1; justify-content: flex-start; }
91
+ .ts-owasp { grid-template-columns: 56px minmax(0, 1fr); }
92
+ .ts-owasp-mid { grid-column: 1 / -1; }
93
+ .ex-band-chips { grid-column: 1 / -1; justify-content: flex-start; }
94
+ .ex-route-controls { align-items: stretch; }
95
+ .ex-route-controls .btn { width: 100%; }
96
+ /* v0.53.0 — `.ex-tool` was the one `.ex-*` block with no entry here at all.
97
+ At this width a tool card's actions are the reason you opened the panel, so
98
+ they go full width rather than being squeezed onto the end of a row. */
99
+ .ex-tool > .row-actions:not(:first-child) { align-items: stretch; }
100
+ .ex-tool > .row-actions:not(:first-child) .btn { width: 100%; }
101
+ /* v0.54.0 — a recovery row's identity is the longest thing in it, so at this
102
+ width it takes its own line rather than truncating a profile and a model
103
+ into nothing. The row is a FLEX COLUMN, so this is a wrap rather than a
104
+ second grid template. */
105
+ .ex-rec-head { flex-wrap: wrap; }
106
+ .ex-rec-who { flex: 1 1 100%; white-space: normal; }
107
+ }
108
+
109
+ @media (max-width: 600px) {
110
+ /* Below this there is no honest way to keep a chip, a slug and an age on one
111
+ line, so the card stacks: chip, then the slug and where it stands, then the
112
+ age. One column, in reading order. */
113
+ .run-card,
114
+ .run-card.no-caret,
115
+ .run-card.has-extra,
116
+ .run-card.no-caret.has-extra {
117
+ grid-template-columns: minmax(0, 1fr);
118
+ gap: var(--sp-2);
119
+ }
120
+ .run-caret { display: none; }
121
+ .run-card .run-age { grid-column: 1; }
122
+ /* Extra: the provider catalog stops being a grid — below this a two-column
123
+ tile cannot hold a base URL and two links without wrapping mid-word — and
124
+ the connect form's two columns become one. */
125
+ .ex-provider-grid { grid-template-columns: minmax(0, 1fr); }
126
+ .ex-strip { gap: var(--sp-3); }
127
+ .ex-route-controls > * { flex: 1 1 100%; }
128
+ /* The tool card's head stops being a row: a label, a binary name and a state
129
+ chip cannot share a line honestly below this. */
130
+ .ex-tool > .row-actions:first-child { flex-direction: column; align-items: flex-start; }
131
+ /* A per-file position line cannot hold a path, a state word and a line delta
132
+ on one row below this — and the path is the half that must stay readable. */
133
+ .ex-rec-file { flex-direction: column; align-items: flex-start; }
134
+
135
+ /* v1.3.0 — the CLI Hook Interface. Every variant that DECLARES columns
136
+ collapses explicitly; the ones that do not (the chip, the palette row) are
137
+ flex and wrap on their own, which is exactly why they were written that
138
+ way. The PREVIEW never collapses: it is a monospaced grid and squeezing it
139
+ would misreport the width the user is deciding. It scrolls instead. */
140
+ .hk-degrade-row,
141
+ .hk-compare-row,
142
+ .hk-field,
143
+ .hk-check {
144
+ grid-template-columns: 1fr;
145
+ gap: 4px;
146
+ }
147
+ .hk-degrade-label,
148
+ .hk-compare-label {
149
+ text-align: left;
150
+ }
151
+ .hk-gallery {
152
+ grid-template-columns: 1fr 1fr;
153
+ }
154
+ .hk-prow-id {
155
+ min-width: 0;
156
+ }
157
+ /* v1.4.1 — the editor's two-column field (a name plus the sentence that
158
+ explains it, then the control) stacks; and DRAG IS OFF below this width. A
159
+ 40-pixel drop gap on a phone is not a target, so the three buttons on every
160
+ chip are the path — which is why they are buttons on the chip and not a
161
+ menu behind one. */
162
+ .hk-chip {
163
+ max-width: none;
164
+ flex-basis: 100%;
165
+ cursor: default;
166
+ }
167
+ .hk-grip { display: none; }
168
+ .hk-add { flex-basis: 100%; }
169
+ .hk-picker, .hk-editor { min-width: 0; }
170
+ .hk-theme { flex-basis: 100%; max-width: none; }
171
+ /* The caution KEEPS its two columns. The mark and the sentence belong to each
172
+ other, and stacking them puts a lone ✕ on a line of its own above the text
173
+ it is about. The mark column narrows instead. */
174
+ .hk-caution {
175
+ grid-template-columns: 14px 1fr;
176
+ gap: 6px;
177
+ }
178
+ }
179
+
180
+ /* The Behaviour panel (v2.0.0 W7) on a phone. No sideways page scroll at 375 px:
181
+ the orbit goes, the tiles pair up, the rows stack, and the heat map keeps all
182
+ 24 columns but labels every other hour. */
183
+ @media (max-width: 860px) {
184
+ .bh-orbit { display: none; }
185
+ .bh-hero { padding: var(--sp-4); }
186
+ .bh-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
187
+ .bh-tile { padding: var(--sp-2) var(--sp-3); }
188
+ .bh-tile-v { font-size: 22px; }
189
+ .bh-portrait li { flex-direction: column; gap: 0; font-size: 14px; }
190
+ .bh-portrait .bh-k { min-width: 0; }
191
+ .bh-tab { padding: 8px 10px; }
192
+ .bh-habit-body { grid-template-columns: 52px minmax(0, 1fr); }
193
+ .bh-ring { width: 52px; height: 52px; }
194
+ .bh-log-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 2px; }
195
+ .bh-log-row .t, .bh-log-row .bh-log-q { grid-column: 1 / -1; }
196
+ .bh-cat { grid-template-columns: minmax(0, 96px) minmax(0, 1fr) 70px; }
197
+ .bh-lesson { grid-template-columns: 48px minmax(0, 1fr); }
198
+ .bh-lesson-right { grid-column: 1 / -1; flex-direction: row; justify-content: flex-start; }
199
+ .bh-heat { grid-template-columns: 26px repeat(24, minmax(0, 1fr)); gap: 2px; }
200
+ .bh-heat .h:nth-child(odd) { visibility: hidden; }
201
+ .bh-lesson > .btn { grid-column: 1 / -1; justify-self: start; }
202
+ .bh-src-bar span { padding: 0; font-size: 0; } /* too narrow to label: the row badges and the title carry the source */
203
+ }
@@ -0,0 +1,205 @@
1
+ /* panels/behaviour.css — orc ui
2
+ The Behaviour panel (v2.0.0 W7): layout only. Motion is NOT here — every
3
+ animation and the ONE reduced-motion block live in 04-motion.css, and the
4
+ phone layout lives in 06-responsive.css. Colours are tokens only: the seven
5
+ series colours --s1 … --s7 are defined in 00-tokens.css.
6
+
7
+ The panel never branches on a CLI word. A state, a class, a `by=` value, a
8
+ gotcha source or status arrives as a `data-*` attribute, and THIS file maps
9
+ it to a token — so a colour is never the only signal (the word is always in
10
+ the chip), and the JS names no state.
11
+
12
+ The <link> ORDER in app.html is the cascade order, and the numeric
13
+ prefix is that order. No @import: it would carry no session token and
14
+ 401. */
15
+
16
+ .bh-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
17
+ .bh-dim { color: var(--text-dim); }
18
+ .bh-faint { color: var(--text-faint); }
19
+
20
+ /* ── head: the learning switch and the window switch ─────────────────────── */
21
+ .bh-headright { display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }
22
+ .bh-seg { display: inline-flex; align-items: center; background: var(--surface-2); border: 1px solid var(--line); border-radius: 100px; padding: 2px; }
23
+ .bh-seg button { border: 0; background: none; padding: 4px 12px; border-radius: 100px; cursor: pointer; color: var(--text-dim); font: inherit; font-size: 12px; }
24
+ .bh-seg button[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: 0 1px 0 var(--line); }
25
+ .bh-seg-mode button[aria-pressed="true"] { background: var(--accent); color: var(--surface); }
26
+ .bh-seg-label { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); padding: 0 8px 0 10px; }
27
+ .bh-seg button:focus-visible, .bh-tab:focus-visible, .bh-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
28
+
29
+ /* ── the hero ────────────────────────────────────────────────────────────── */
30
+ .bh-hero {
31
+ position: relative; overflow: hidden; border-radius: var(--radius-lg); border: 1px solid var(--line);
32
+ padding: var(--sp-5) var(--sp-5) var(--sp-4);
33
+ background: radial-gradient(900px 260px at 0% 0%, var(--accent-wash), transparent 60%), var(--surface);
34
+ display: flex; flex-direction: column; gap: var(--sp-3);
35
+ }
36
+ .bh-eyebrow { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--text-faint); display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
37
+ .bh-portrait { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
38
+ .bh-portrait li { font-size: 15px; line-height: 1.45; display: flex; gap: 10px; align-items: baseline; }
39
+ .bh-portrait .bh-k { font-size: 11px; color: var(--text-faint); min-width: 70px; }
40
+ .bh-orbit { position: absolute; right: -40px; top: -40px; width: 260px; height: 260px; opacity: .55; pointer-events: none; }
41
+ .bh-orbit circle { fill: none; stroke: var(--line); stroke-width: 1; }
42
+ .bh-orbit .sat { fill: var(--accent); stroke: none; }
43
+ .bh-off-title { font-size: 18px; font-weight: 650; }
44
+ .bh-off-list { margin: 0 0 0 18px; display: flex; flex-direction: column; gap: 6px; color: var(--text-dim); }
45
+ .bh-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--sp-3); }
46
+ .bh-tile { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--sp-3) var(--sp-4); min-width: 0; }
47
+ .bh-tile-l { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); }
48
+ .bh-tile-v { font-size: 28px; font-weight: 650; letter-spacing: -.02em; line-height: 1.15; margin-top: 2px; font-variant-numeric: tabular-nums; }
49
+ .bh-tile-v small { font-size: 13px; color: var(--text-dim); font-weight: 500; margin-left: 6px; }
50
+ .bh-tile-n { font-size: 11px; color: var(--text-dim); }
51
+ .chip[data-mode="propose"] { background: var(--accent-wash); color: var(--accent); }
52
+
53
+ /* ── the tabs ────────────────────────────────────────────────────────────── */
54
+ .bh-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); position: relative; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
55
+ .bh-tab { flex: none; white-space: nowrap; }
56
+ .bh-tab { border: 0; background: none; padding: 10px 14px; cursor: pointer; color: var(--text-dim); font: inherit; font-weight: 550; display: flex; gap: 6px; align-items: center; border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
57
+ .bh-tab:hover { color: var(--text); background: var(--surface-2); }
58
+ .bh-tab[aria-selected="true"] { color: var(--text); }
59
+ .bh-count { font-family: var(--mono); font-size: 10px; padding: 1px 6px; border-radius: 100px; background: var(--surface-3); color: var(--text-dim); }
60
+ .bh-count.hot { background: var(--accent-wash); color: var(--accent); }
61
+ .bh-tab-ink { position: absolute; bottom: 0; left: 0; width: 0; height: 2px; background: var(--accent); border-radius: 2px; }
62
+
63
+ /* ── the CLI's words, mapped to tokens ───────────────────────────────────── */
64
+ .chip[data-state="proposed"], .chip[data-status="candidate"] { background: var(--accent-wash); color: var(--accent); }
65
+ .chip[data-state="applied"], .chip[data-status="active"], .chip[data-sync="ok"] { background: var(--ok-wash); color: var(--ok); }
66
+ .chip[data-state="stale"], .chip[data-state="shadowed"], .chip[data-status="quiet"], .chip[data-sync="timed out"] { background: var(--warn-wash); color: var(--warn); }
67
+ .chip[data-state="never"], .chip[data-status="orphaned"], .chip[data-sync="failed"] { background: var(--bad-wash); color: var(--bad); }
68
+ .chip[data-by="ledger"] { background: var(--warn-wash); color: var(--warn); }
69
+ .chip[data-by="learned"] { background: var(--accent-wash); color: var(--accent); }
70
+ .chip[data-by="config"] { background: var(--ok-wash); color: var(--ok); }
71
+ .bh-cls { font-family: var(--mono); font-size: 10px; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--line); color: var(--text-dim); }
72
+ .bh-cls[data-cls="apply"] { border-color: color-mix(in srgb, var(--ok) 45%, var(--line)); color: var(--ok); }
73
+ .bh-cls[data-cls="suggest"] { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); color: var(--accent); }
74
+ .bh-cls[data-cls="never"] { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); color: var(--bad); }
75
+
76
+ /* ── Habits ──────────────────────────────────────────────────────────────── */
77
+ .bh-legend { display: flex; gap: var(--sp-2) var(--sp-4); flex-wrap: wrap; align-items: center; }
78
+ .bh-next { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
79
+ .bh-next li { display: flex; gap: var(--sp-2); align-items: baseline; flex-wrap: wrap; }
80
+ .bh-habits { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); gap: var(--sp-4); }
81
+ .bh-habit { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
82
+ .bh-habit:hover { border-color: var(--text-faint); box-shadow: var(--shadow); }
83
+ .bh-habit:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
84
+ .bh-habit[data-state="proposed"] { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
85
+ .bh-habit[data-state="never"] { background: repeating-linear-gradient(135deg, var(--surface), var(--surface) 10px, var(--surface-2) 10px, var(--surface-2) 20px); }
86
+ .bh-habit-top { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
87
+ .bh-habit-top > .chip { margin-left: auto; }
88
+ .bh-lane { font-size: 11px; color: var(--text-dim); background: var(--surface-2); border: 1px solid var(--line-soft); padding: 1px 7px; border-radius: var(--radius-sm); }
89
+ .bh-qid { font-size: 11px; color: var(--text-faint); overflow-wrap: anywhere; }
90
+ .bh-habit-body { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: var(--sp-3); align-items: center; }
91
+ .bh-habit h3 { font-size: 15px; font-weight: 600; margin: 0; }
92
+ .bh-line { color: var(--text-dim); font-size: 12.5px; }
93
+ .bh-ring { width: 64px; height: 64px; }
94
+ .bh-ring .bg { fill: none; stroke: var(--surface-3); stroke-width: 6; }
95
+ .bh-ring .fg { fill: none; stroke-width: 6; stroke-linecap: round; transform: rotate(-90deg); transform-origin: 50% 50%; stroke: var(--accent); }
96
+ .bh-ring[data-state="applied"] .fg { stroke: var(--ok); }
97
+ .bh-ring[data-state="stale"] .fg, .bh-ring[data-state="shadowed"] .fg { stroke: var(--warn); }
98
+ .bh-ring[data-state="never"] .fg { stroke: var(--bad); }
99
+ .bh-ring[data-state="observed"] .fg, .bh-ring[data-state="declined"] .fg, .bh-ring[data-state="never-ask"] .fg { stroke: var(--idle); }
100
+ .bh-ring text { font: 600 14px var(--font); fill: var(--text); text-anchor: middle; dominant-baseline: central; }
101
+ .bh-ring text.s { font-size: 9px; fill: var(--text-faint); font-weight: 500; }
102
+ .bh-dist { display: flex; height: 10px; border-radius: 100px; overflow: hidden; background: var(--surface-3); gap: 2px; }
103
+ .bh-dist span { display: block; height: 100%; border-radius: 2px; background: var(--text-faint); }
104
+ .bh-dist span.is-top { background: var(--accent); }
105
+ .bh-habit[data-state="never"] .bh-dist span.is-top { background: var(--bad); }
106
+ .bh-habit[data-state="stale"] .bh-dist span.is-top { background: var(--warn); }
107
+ .bh-dist-legend { display: flex; gap: var(--sp-2) var(--sp-3); flex-wrap: wrap; font-size: 11px; color: var(--text-dim); align-items: center; }
108
+ .bh-dist-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 5px; background: var(--text-faint); }
109
+ .bh-dist-legend i.is-top { background: var(--accent); }
110
+ .bh-habit-meta { display: flex; gap: var(--sp-2) var(--sp-3); flex-wrap: wrap; font-size: 11px; color: var(--text-faint); align-items: center; }
111
+ .bh-habit-meta b { color: var(--text-dim); font-weight: 500; overflow-wrap: anywhere; }
112
+ .bh-streak { display: flex; gap: 3px; font-size: 11px; line-height: 1; font-family: var(--mono); }
113
+ .bh-streak i { font-style: normal; width: 11px; text-align: center; color: var(--text-faint); }
114
+ .bh-streak i.on { color: var(--accent); }
115
+ .bh-why { font-size: 11.5px; color: var(--text-dim); border-left: 2px solid var(--line); padding-left: var(--sp-2); }
116
+ .bh-actions-wrap { display: flex; flex-direction: column; gap: var(--sp-2); }
117
+ .bh-actions-wrap:empty { display: none; }
118
+ .bh-cmd { display: flex; align-items: center; gap: var(--sp-2); font-size: 11px; color: var(--text-dim); background: var(--surface-2); border: 1px dashed var(--line); border-radius: var(--radius-sm); padding: 4px 8px; min-width: 0; }
119
+ .bh-cmd .mono { overflow-wrap: anywhere; min-width: 0; }
120
+ .bh-cmd .copy-btn { margin-left: auto; flex: none; }
121
+ .bh-history { display: flex; flex-direction: column; gap: var(--sp-2); }
122
+ .bh-hist-row { display: flex; gap: var(--sp-2) var(--sp-3); align-items: center; flex-wrap: wrap; font-size: 12px; }
123
+
124
+ /* ── Rhythm ──────────────────────────────────────────────────────────────── */
125
+ .bh-heat { display: grid; grid-template-columns: 34px repeat(24, minmax(0, 1fr)); gap: 3px; align-items: center; }
126
+ .bh-heat .h { font-size: 9px; color: var(--text-faint); text-align: center; font-family: var(--mono); }
127
+ .bh-heat .d { font-size: 10px; color: var(--text-faint); font-family: var(--mono); }
128
+ .bh-heat .c { aspect-ratio: 1; border-radius: 3px; background: var(--surface-3); }
129
+ .bh-heat .c:hover { outline: 1px solid var(--text-faint); }
130
+ .bh-mix { display: flex; height: 22px; border-radius: 6px; overflow: hidden; gap: 2px; }
131
+ .bh-mix span { display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: var(--bg); white-space: nowrap; overflow: hidden; min-width: 0; }
132
+ .bh-mix-legend { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px var(--sp-4); font-size: 12px; }
133
+ .bh-mix-legend div { display: flex; align-items: center; gap: 8px; min-width: 0; }
134
+ .bh-mix-legend i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
135
+ .bh-mix-legend .bh-dim { margin-left: auto; }
136
+ .bh-chart { width: 100%; height: 150px; display: block; }
137
+ .bh-chart .grid-l { stroke: var(--line-soft); stroke-width: 1; }
138
+ .bh-chart .ln { fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; stroke: var(--accent); }
139
+ .bh-chart .pt { stroke: var(--surface); stroke-width: 2; fill: var(--accent); }
140
+ .bh-chart[data-kind="ok"] .ln { stroke: var(--ok); }
141
+ .bh-chart[data-kind="ok"] .pt { fill: var(--ok); }
142
+ .bh-chart[data-kind="warn"] .ln { stroke: var(--warn); }
143
+ .bh-chart[data-kind="warn"] .pt { fill: var(--warn); }
144
+ .bh-chart .target { stroke: var(--ok); stroke-dasharray: 4 4; stroke-width: 1; }
145
+ .bh-chart text { font: 10px var(--mono); fill: var(--text-faint); }
146
+ .bh-how { display: flex; align-items: flex-end; gap: 6px; height: 130px; padding-top: 6px; }
147
+ .bh-how-col { flex: 1; display: flex; flex-direction: column-reverse; gap: 2px; height: 100%; min-width: 0; }
148
+ .bh-how-col span { display: block; border-radius: 3px; width: 100%; }
149
+ [data-by="user"].bh-grow-y, .bh-dist-legend i[data-by="user"] { background: var(--s7); }
150
+ [data-by="ledger"].bh-grow-y, .bh-dist-legend i[data-by="ledger"] { background: var(--s3); }
151
+ [data-by="learned"].bh-grow-y, .bh-dist-legend i[data-by="learned"] { background: var(--s1); }
152
+ [data-by="config"].bh-grow-y, .bh-dist-legend i[data-by="config"] { background: var(--s2); }
153
+ [data-by="default"].bh-grow-y, .bh-dist-legend i[data-by="default"] { background: var(--s4); }
154
+
155
+ /* ── Gotchas ─────────────────────────────────────────────────────────────── */
156
+ .bh-src-bar { display: flex; height: 26px; border-radius: 7px; overflow: hidden; gap: 2px; }
157
+ .bh-src-bar span { display: flex; align-items: center; padding: 0 8px; font-size: 11px; font-weight: 600; color: var(--bg); white-space: nowrap; overflow: hidden; min-width: 0; }
158
+ [data-source="repair"] { background: var(--s6); }
159
+ [data-source="drift"] { background: var(--s4); }
160
+ [data-source="review"] { background: var(--s2); }
161
+ [data-source="verify"] { background: var(--s3); }
162
+ [data-source="defect"] { background: var(--s5); }
163
+ [data-source="pr"] { background: var(--s1); }
164
+ [data-source="sonar"] { background: var(--s5); }
165
+ [data-source="sarif"] { background: var(--s4); }
166
+ [data-source="ci"] { background: var(--s3); }
167
+ [data-source="dismissal"] { background: var(--s7); }
168
+ .bh-lesson { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; padding: var(--sp-3) 0; border-top: 1px solid var(--line-soft); }
169
+ .card > .bh-lesson:first-of-type { border-top: 0; }
170
+ .bh-lesson-id { font-size: 12px; color: var(--text-dim); }
171
+ .bh-lesson-rule { font-size: 13px; overflow-wrap: anywhere; }
172
+ .bh-lesson-sub { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; margin-top: 3px; font-size: 11px; color: var(--text-faint); }
173
+ .bh-scope { color: var(--text-dim); overflow-wrap: anywhere; }
174
+ .bh-src { font-size: 10px; padding: 1px 6px; border-radius: 4px; color: var(--bg); }
175
+ .bh-lesson-right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
176
+ .bh-spark { display: flex; align-items: flex-end; gap: 2px; height: 22px; }
177
+ .bh-spark i { width: 4px; border-radius: 1px; background: var(--accent); opacity: .8; }
178
+ .bh-spark i.zero { opacity: .25; }
179
+ .bh-input { width: 100%; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 7px 10px; color: var(--text); font: 12px var(--mono); }
180
+ .bh-card-out { font-size: 11.5px; line-height: 1.6; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: var(--sp-3); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-dim); min-height: 90px; margin: 0; }
181
+
182
+ /* ── Review quality ──────────────────────────────────────────────────────── */
183
+ .bh-cat { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr) 90px; gap: var(--sp-3); align-items: center; padding: 6px 0; }
184
+ .bh-cat-name { font-size: 11.5px; overflow-wrap: anywhere; }
185
+ .bh-cat-bar { height: 10px; background: var(--surface-3); border-radius: 100px; position: relative; }
186
+ .bh-cat-bar span { display: block; height: 100%; border-radius: 100px; }
187
+ .bh-cat-bar span[data-band="ok"] { background: var(--ok); }
188
+ .bh-cat-bar span[data-band="warn"] { background: var(--warn); }
189
+ .bh-cat-bar span[data-band="bad"] { background: var(--bad); }
190
+ .bh-cat-bar .tick { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--text-faint); opacity: .6; }
191
+ .bh-cat-num { font-size: 11px; color: var(--text-dim); text-align: right; }
192
+ .bh-floor { font-size: 12px; color: var(--text-dim); border: 1px dashed var(--line); border-radius: var(--radius-sm); padding: var(--sp-4); text-align: center; }
193
+
194
+ /* ── Answer log ──────────────────────────────────────────────────────────── */
195
+ .bh-log-row { display: grid; grid-template-columns: 150px 90px minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; padding: 8px 0; border-top: 1px solid var(--line-soft); font-size: 12.5px; }
196
+ .bh-log-row:first-child { border-top: 0; }
197
+ .bh-log-row .t { font-size: 11px; color: var(--text-faint); }
198
+ .bh-log-row .ln { font-size: 11px; color: var(--text-dim); }
199
+ .bh-log-q { overflow-wrap: anywhere; }
200
+
201
+ /* ── footer + rail dot ───────────────────────────────────────────────────── */
202
+ .bh-foot { display: flex; gap: var(--sp-2) var(--sp-4); flex-wrap: wrap; align-items: center; font-size: 11.5px; color: var(--text-faint); }
203
+ .bh-foot .mono { overflow-wrap: anywhere; }
204
+ .bh-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); margin-left: 6px; vertical-align: middle; }
205
+ .bh-tabpanel pre.cmd { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0; }