rcf-lite 0.0.1 → 0.8.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 (349) hide show
  1. package/CHANGELOG.md +344 -0
  2. package/LICENSE +202 -0
  3. package/README.md +92 -4
  4. package/bin/rcf-verify.js +122 -0
  5. package/bin/rcf.js +174 -0
  6. package/bin/view-supervisor-child.mjs +14 -0
  7. package/fixtures/canary-manifest.json +103 -0
  8. package/guidance/README.md +25 -0
  9. package/guidance/build-cycle-playbook.md +492 -0
  10. package/guidance/build-cycle.md +40 -0
  11. package/guidance/document-model.md +45 -0
  12. package/guidance/elicitation-playbook.md +442 -0
  13. package/guidance/harness-template.md +246 -0
  14. package/guidance/managed/README.md +63 -0
  15. package/guidance/managed/agent-instructions-block.hash +1 -0
  16. package/guidance/managed/agent-instructions-block.md +220 -0
  17. package/guidance/managed/legacy-fragment-hashes.json +22 -0
  18. package/guidance/manifest.json +21 -0
  19. package/guidance/overview.md +48 -0
  20. package/guidance/persona-programme.md +44 -0
  21. package/package.json +71 -8
  22. package/rcf/adrs/adr-001.json +25 -0
  23. package/rcf/adrs/adr-002.json +25 -0
  24. package/rcf/adrs/adr-003.json +25 -0
  25. package/rcf/adrs/adr-004.json +20 -0
  26. package/rcf/adrs/adr-005.json +20 -0
  27. package/rcf/adrs/adr-006.json +25 -0
  28. package/rcf/adrs/adr-007.json +25 -0
  29. package/rcf/adrs/adr-008.json +25 -0
  30. package/rcf/adrs/adr-009.json +25 -0
  31. package/rcf/build-sequence.json +11 -0
  32. package/rcf/code-nodes/cn-001.json +14 -0
  33. package/rcf/code-nodes/cn-002.json +14 -0
  34. package/rcf/code-nodes/cn-003.json +15 -0
  35. package/rcf/code-nodes/cn-004.json +17 -0
  36. package/rcf/code-nodes/cn-005.json +19 -0
  37. package/rcf/code-nodes/cn-006.json +17 -0
  38. package/rcf/code-nodes/cn-007.json +16 -0
  39. package/rcf/code-nodes/cn-008.json +19 -0
  40. package/rcf/code-nodes/cn-009.json +16 -0
  41. package/rcf/code-nodes/cn-010.json +18 -0
  42. package/rcf/code-nodes/cn-011.json +18 -0
  43. package/rcf/code-nodes/cn-012.json +18 -0
  44. package/rcf/code-nodes/cn-013.json +19 -0
  45. package/rcf/code-nodes/cn-014.json +16 -0
  46. package/rcf/code-nodes/cn-015.json +16 -0
  47. package/rcf/code-nodes/cn-016.json +16 -0
  48. package/rcf/code-nodes/cn-017.json +16 -0
  49. package/rcf/code-nodes/cn-018.json +15 -0
  50. package/rcf/code-nodes/cn-019.json +16 -0
  51. package/rcf/code-nodes/cn-020.json +16 -0
  52. package/rcf/code-nodes/cn-021.json +16 -0
  53. package/rcf/code-nodes/cn-022.json +16 -0
  54. package/rcf/code-nodes/cn-023.json +16 -0
  55. package/rcf/code-nodes/cn-024.json +16 -0
  56. package/rcf/code-nodes/cn-025.json +16 -0
  57. package/rcf/code-nodes/cn-026.json +16 -0
  58. package/rcf/code-nodes/cn-027.json +16 -0
  59. package/rcf/code-nodes/cn-028.json +16 -0
  60. package/rcf/code-nodes/cn-029.json +19 -0
  61. package/rcf/code-nodes/cn-030.json +14 -0
  62. package/rcf/code-nodes/cn-031.json +14 -0
  63. package/rcf/code-nodes/cn-032.json +14 -0
  64. package/rcf/code-nodes/cn-033.json +14 -0
  65. package/rcf/code-nodes/cn-034.json +14 -0
  66. package/rcf/code-nodes/cn-035.json +14 -0
  67. package/rcf/code-nodes/cn-036.json +14 -0
  68. package/rcf/code-nodes/cn-037.json +14 -0
  69. package/rcf/code-nodes/cn-038.json +14 -0
  70. package/rcf/code-nodes/cn-039.json +14 -0
  71. package/rcf/code-nodes/cn-040.json +14 -0
  72. package/rcf/code-nodes/cn-041.json +14 -0
  73. package/rcf/code-nodes/cn-042.json +14 -0
  74. package/rcf/code-nodes/cn-043.json +14 -0
  75. package/rcf/code-nodes/cn-044.json +14 -0
  76. package/rcf/code-nodes/cn-045.json +14 -0
  77. package/rcf/code-nodes/cn-046.json +14 -0
  78. package/rcf/code-nodes/cn-047.json +14 -0
  79. package/rcf/code-nodes/cn-048.json +14 -0
  80. package/rcf/code-nodes/cn-049.json +14 -0
  81. package/rcf/code-nodes/cn-050.json +14 -0
  82. package/rcf/code-nodes/cn-051.json +14 -0
  83. package/rcf/code-nodes/cn-052.json +14 -0
  84. package/rcf/code-nodes/cn-053.json +14 -0
  85. package/rcf/code-nodes/cn-054.json +14 -0
  86. package/rcf/code-nodes/cn-055.json +14 -0
  87. package/rcf/code-nodes/cn-056.json +14 -0
  88. package/rcf/code-nodes/cn-057.json +14 -0
  89. package/rcf/fbs/fbs-001.json +49 -0
  90. package/rcf/fbs/fbs-002.json +42 -0
  91. package/rcf/fbs/fbs-003.json +37 -0
  92. package/rcf/fbs/fbs-004.json +39 -0
  93. package/rcf/fbs/fbs-005.json +38 -0
  94. package/rcf/fbs/fbs-006.json +48 -0
  95. package/rcf/fbs/fbs-007.json +39 -0
  96. package/rcf/fbs/fbs-008.json +40 -0
  97. package/rcf/fbs/fbs-009.json +36 -0
  98. package/rcf/fbs/fbs-010.json +41 -0
  99. package/rcf/fbs/fbs-011.json +36 -0
  100. package/rcf/fbs/fbs-012.json +46 -0
  101. package/rcf/fbs/fbs-013.json +42 -0
  102. package/rcf/fbs/fbs-014.json +49 -0
  103. package/rcf/fbs/fbs-015.json +32 -0
  104. package/rcf/manifest.json +17 -0
  105. package/rcf/prd.json +47 -0
  106. package/rcf/requirements/req-001.json +19 -0
  107. package/rcf/requirements/req-002.json +19 -0
  108. package/rcf/requirements/req-003.json +19 -0
  109. package/rcf/requirements/req-004.json +19 -0
  110. package/rcf/requirements/req-005.json +19 -0
  111. package/rcf/requirements/req-006.json +19 -0
  112. package/rcf/requirements/req-007.json +19 -0
  113. package/rcf/requirements/req-008.json +19 -0
  114. package/rcf/requirements/req-009.json +19 -0
  115. package/rcf/tacs/tac-001.json +45 -0
  116. package/rcf/tacs/tac-002.json +109 -0
  117. package/rcf/tacs/tac-003.json +40 -0
  118. package/rcf/tacs/tac-004.json +51 -0
  119. package/rcf/tacs/tac-005.json +52 -0
  120. package/rcf/tacs/tac-006.json +104 -0
  121. package/rcf/tacs/tac-007.json +38 -0
  122. package/rcf/tacs/tac-008.json +51 -0
  123. package/rcf/tad.json +51 -0
  124. package/rcf/test-suites/PENDING.md +23 -0
  125. package/rcf/test-suites/ts-001.json +38 -0
  126. package/rcf/test-suites/ts-002.json +38 -0
  127. package/rcf/test-suites/ts-003.json +43 -0
  128. package/rcf/test-suites/ts-004.json +44 -0
  129. package/rcf/test-suites/ts-005.json +30 -0
  130. package/rcf/test-suites/ts-006.json +36 -0
  131. package/rcf/test-suites/ts-007.json +43 -0
  132. package/rcf/test-suites/ts-008.json +37 -0
  133. package/rcf/test-suites/ts-009.json +38 -0
  134. package/rcf/test-suites/ts-010.json +38 -0
  135. package/rcf/test-suites/ts-011.json +44 -0
  136. package/rcf/test-suites/ts-012.json +36 -0
  137. package/rcf/test-suites/ts-013.json +38 -0
  138. package/rcf/test-suites/ts-014.json +38 -0
  139. package/rcf/test-suites/ts-015.json +38 -0
  140. package/rcf/test-suites/ts-016.json +37 -0
  141. package/rcf/test-suites/ts-017.json +38 -0
  142. package/rcf/test-suites/ts-018.json +38 -0
  143. package/rcf/test-suites/ts-019.json +37 -0
  144. package/rcf/test-suites/ts-020.json +46 -0
  145. package/rcf/test-suites/ts-021.json +46 -0
  146. package/rcf/test-suites/ts-022.json +46 -0
  147. package/rcf/test-suites/ts-023.json +46 -0
  148. package/rcf/test-suites/ts-024.json +46 -0
  149. package/rcf/test-suites/ts-025.json +52 -0
  150. package/rcf/user-stories/us-101.json +40 -0
  151. package/rcf/user-stories/us-102.json +40 -0
  152. package/rcf/user-stories/us-201.json +40 -0
  153. package/rcf/user-stories/us-202.json +40 -0
  154. package/rcf/user-stories/us-203.json +32 -0
  155. package/rcf/user-stories/us-301.json +40 -0
  156. package/rcf/user-stories/us-302.json +40 -0
  157. package/rcf/user-stories/us-303.json +40 -0
  158. package/rcf/user-stories/us-304.json +40 -0
  159. package/rcf/user-stories/us-401.json +40 -0
  160. package/rcf/user-stories/us-402.json +40 -0
  161. package/rcf/user-stories/us-403.json +40 -0
  162. package/rcf/user-stories/us-501.json +40 -0
  163. package/rcf/user-stories/us-502.json +40 -0
  164. package/rcf/user-stories/us-503.json +40 -0
  165. package/rcf/user-stories/us-601.json +40 -0
  166. package/rcf/user-stories/us-602.json +40 -0
  167. package/rcf/user-stories/us-701.json +40 -0
  168. package/rcf/user-stories/us-702.json +40 -0
  169. package/rcf/user-stories/us-801.json +49 -0
  170. package/rcf/user-stories/us-802.json +49 -0
  171. package/rcf/user-stories/us-803.json +49 -0
  172. package/rcf/user-stories/us-804.json +49 -0
  173. package/rcf/user-stories/us-805.json +49 -0
  174. package/rcf/user-stories/us-901.json +40 -0
  175. package/src/.gitkeep +0 -0
  176. package/src/admissibility/enforce.js +142 -0
  177. package/src/admissibility/index.js +8 -0
  178. package/src/admissibility/markers.js +104 -0
  179. package/src/admissibility/scope-lint.js +163 -0
  180. package/src/browser-verify/auth-smoke.js +109 -0
  181. package/src/browser-verify/index.js +29 -0
  182. package/src/browser-verify/invariants.js +336 -0
  183. package/src/browser-verify/manifest-writer.js +189 -0
  184. package/src/browser-verify/runner.js +171 -0
  185. package/src/build/bundle.js +198 -0
  186. package/src/build/formatters/json.js +18 -0
  187. package/src/build/formatters/markdown.js +406 -0
  188. package/src/build/index.js +14 -0
  189. package/src/build/mark.js +177 -0
  190. package/src/build/queue.js +285 -0
  191. package/src/cli/browser-verify.js +231 -0
  192. package/src/cli/build.js +584 -0
  193. package/src/cli/coverage.js +219 -0
  194. package/src/cli/create.js +358 -0
  195. package/src/cli/delete.js +127 -0
  196. package/src/cli/design.js +353 -0
  197. package/src/cli/doctor.js +548 -0
  198. package/src/cli/fbs.js +171 -0
  199. package/src/cli/finalise.js +377 -0
  200. package/src/cli/guidance.js +206 -0
  201. package/src/cli/help.js +156 -0
  202. package/src/cli/impact.js +119 -0
  203. package/src/cli/init.js +282 -0
  204. package/src/cli/intake.js +153 -0
  205. package/src/cli/link.js +128 -0
  206. package/src/cli/mcp.js +160 -0
  207. package/src/cli/preflight.js +220 -0
  208. package/src/cli/read.js +168 -0
  209. package/src/cli/req-baseline.js +269 -0
  210. package/src/cli/req-classify.js +135 -0
  211. package/src/cli/review.js +295 -0
  212. package/src/cli/test-suite.js +221 -0
  213. package/src/cli/trace.js +172 -0
  214. package/src/cli/ui-baseline.js +292 -0
  215. package/src/cli/ui-classify.js +108 -0
  216. package/src/cli/update.js +197 -0
  217. package/src/cli/validate.js +168 -0
  218. package/src/cli/view.js +452 -0
  219. package/src/core/baseline-catalog/data/auth.json +42 -0
  220. package/src/core/baseline-catalog/data/http-api.json +42 -0
  221. package/src/core/baseline-catalog/data/notifications.json +33 -0
  222. package/src/core/baseline-catalog/data/persistence.json +33 -0
  223. package/src/core/baseline-catalog/data/web-ui.json +60 -0
  224. package/src/core/baseline-catalog/index.js +121 -0
  225. package/src/core/errors/index.js +167 -0
  226. package/src/core/fixtures/register-canary/canary-prompt-01.json +18 -0
  227. package/src/core/fixtures/register-canary/canary-prompt-02.json +21 -0
  228. package/src/core/fixtures/register-canary/canary-prompt-03.json +17 -0
  229. package/src/core/isolation/index.js +60 -0
  230. package/src/core/mcp/framing.js +103 -0
  231. package/src/core/mcp/index.js +8 -0
  232. package/src/core/mcp/server.js +228 -0
  233. package/src/core/patterns/register-canary.js +209 -0
  234. package/src/core/patterns/req-shapes.js +158 -0
  235. package/src/core/patterns/services.js +358 -0
  236. package/src/core/patterns/ui-shapes.js +166 -0
  237. package/src/core/store/cn-resolve.js +134 -0
  238. package/src/core/store/derive-deps.js +93 -0
  239. package/src/core/store/ids.js +78 -0
  240. package/src/core/store/index.js +20 -0
  241. package/src/core/store/init.js +255 -0
  242. package/src/core/store/loader.js +214 -0
  243. package/src/core/store/tp-resolve.js +176 -0
  244. package/src/core/store/validator.js +191 -0
  245. package/src/core/store/walker.js +944 -0
  246. package/src/core/store/writer.js +1879 -0
  247. package/src/design/index.js +11 -0
  248. package/src/design/writer.js +271 -0
  249. package/src/finalise/detect.js +151 -0
  250. package/src/finalise/index.js +31 -0
  251. package/src/finalise/ingest.js +160 -0
  252. package/src/finalise/install.js +119 -0
  253. package/src/finalise/ship-without-verified.js +131 -0
  254. package/src/finalise/spawn.js +84 -0
  255. package/src/intake/fidelity.js +105 -0
  256. package/src/intake/index.js +6 -0
  257. package/src/intake/manifest-writer.js +100 -0
  258. package/src/intake/orchestrator.js +138 -0
  259. package/src/intake/validate.js +80 -0
  260. package/src/mcp/map-errors.js +131 -0
  261. package/src/mcp/prompts.js +49 -0
  262. package/src/mcp/resources.js +244 -0
  263. package/src/mcp/tools.js +1212 -0
  264. package/src/preflight/design-shapes.js +185 -0
  265. package/src/preflight/index.js +90 -0
  266. package/src/preflight/manifest-writer.js +264 -0
  267. package/src/preflight/scanner.js +206 -0
  268. package/src/preflight/secrets.js +134 -0
  269. package/src/preflight/session.js +246 -0
  270. package/src/query/attestation.js +285 -0
  271. package/src/query/coverage.js +308 -0
  272. package/src/query/formatters/json.js +21 -0
  273. package/src/query/formatters/mermaid.js +209 -0
  274. package/src/query/formatters/table.js +203 -0
  275. package/src/query/impact.js +173 -0
  276. package/src/query/index.js +13 -0
  277. package/src/query/refuse-on-admissibility.js +73 -0
  278. package/src/query/trace.js +345 -0
  279. package/src/register-canary/fixture-loader.js +87 -0
  280. package/src/register-canary/index.js +10 -0
  281. package/src/register-canary/record-writer.js +132 -0
  282. package/src/register-canary/runner.js +156 -0
  283. package/src/req-baseline/gate.js +86 -0
  284. package/src/req-baseline/index.js +27 -0
  285. package/src/req-baseline/open-candidates.js +143 -0
  286. package/src/req-baseline/opt-out.js +195 -0
  287. package/src/req-baseline/sweep.js +230 -0
  288. package/src/req-detection/classifier.js +181 -0
  289. package/src/req-detection/index.js +9 -0
  290. package/src/req-detection/persist.js +55 -0
  291. package/src/review/index.js +325 -0
  292. package/src/review/mutation.js +117 -0
  293. package/src/review/ui-baseline-drift.js +138 -0
  294. package/src/ruleset/index.js +140 -0
  295. package/src/ruleset/ruleset.json +146 -0
  296. package/src/server/index.js +178 -0
  297. package/src/server/routes.js +110 -0
  298. package/src/server/sse.js +118 -0
  299. package/src/setup/agent-setup.js +362 -0
  300. package/src/setup/identity-seed.js +104 -0
  301. package/src/setup/knowledge-seed.js +123 -0
  302. package/src/setup/managed-block.js +193 -0
  303. package/src/setup/managed-gitignore.js +166 -0
  304. package/src/setup/managed-markers.js +49 -0
  305. package/src/ui-baseline/defaults.js +119 -0
  306. package/src/ui-baseline/index.js +25 -0
  307. package/src/ui-baseline/manifest-writer.js +282 -0
  308. package/src/ui-baseline/session.js +178 -0
  309. package/src/ui-detection/classifier.js +192 -0
  310. package/src/verify/chain/index.js +221 -0
  311. package/src/verify/cli/cleanup.js +61 -0
  312. package/src/verify/cli/help.js +56 -0
  313. package/src/verify/cli/mcp.js +98 -0
  314. package/src/verify/cli/provision.js +71 -0
  315. package/src/verify/cli/report.js +71 -0
  316. package/src/verify/cli/run.js +155 -0
  317. package/src/verify/engine/brief.js +87 -0
  318. package/src/verify/engine/index.js +177 -0
  319. package/src/verify/engine/launcher.js +307 -0
  320. package/src/verify/mcp/tools.js +107 -0
  321. package/src/verify/profile/index.js +146 -0
  322. package/src/verify/provision/index.js +256 -0
  323. package/src/verify/report/index.js +139 -0
  324. package/src/verify/report/renderer.js +118 -0
  325. package/src/verify/verdict/index.js +313 -0
  326. package/src/view/doc-renderers/adr.js +44 -0
  327. package/src/view/doc-renderers/build-sequence.js +40 -0
  328. package/src/view/doc-renderers/fbs.js +128 -0
  329. package/src/view/doc-renderers/helpers.js +159 -0
  330. package/src/view/doc-renderers/index.js +12 -0
  331. package/src/view/doc-renderers/prd.js +45 -0
  332. package/src/view/doc-renderers/req.js +43 -0
  333. package/src/view/doc-renderers/tac.js +38 -0
  334. package/src/view/doc-renderers/tad.js +74 -0
  335. package/src/view/doc-renderers/test-suite.js +45 -0
  336. package/src/view/doc-renderers/user-story.js +63 -0
  337. package/src/view/html-page.js +462 -0
  338. package/src/view/index.js +63 -0
  339. package/src/view/live-client.js +338 -0
  340. package/src/view/mermaid-diagram.js +178 -0
  341. package/src/view/style.css +735 -0
  342. package/src/view/tree-model.js +152 -0
  343. package/src/view/vendored/mermaid.min.js +2607 -0
  344. package/src/view-supervisor/index.js +26 -0
  345. package/src/view-supervisor/logs.js +32 -0
  346. package/src/view-supervisor/manifest-writer.js +178 -0
  347. package/src/view-supervisor/persist-until.js +85 -0
  348. package/src/view-supervisor/supervisor.js +276 -0
  349. package/src/watch/index.js +152 -0
@@ -0,0 +1,735 @@
1
+ /*
2
+ * RCF view stylesheet. Vanilla CSS, no preprocessor, no framework.
3
+ * Document-type colour tokens match the Mermaid classDef palette in
4
+ * mermaid-diagram.js so the diagram and the page agree visually.
5
+ *
6
+ * Phase 3.3 polish: warmer surface palette, subtle card shadows + hover,
7
+ * sticky tab bar with backdrop-blur, indigo accent, wider spacing rhythm,
8
+ * refined typography stack. Same information density; nicer to look at.
9
+ */
10
+
11
+ :root {
12
+ color-scheme: light;
13
+
14
+ /* Neutrals - slightly warmer than pure greys */
15
+ --colour-text: #0f172a;
16
+ --colour-heading: #0b1220;
17
+ --colour-muted: #6b7280;
18
+ --colour-subtle: #94a3b8;
19
+ --colour-bg: #fdfdfd;
20
+ --colour-surface: #f7f8fa;
21
+ --colour-surface-2: #eef1f6;
22
+ --colour-border: #e4e7ec;
23
+ --colour-border-strong: #cbd5e1;
24
+
25
+ /* Accent - indigo. Distinctive but professional. */
26
+ --colour-accent: #4f46e5;
27
+ --colour-accent-hover: #4338ca;
28
+ --colour-accent-subtle: #eef2ff;
29
+ --colour-link: var(--colour-accent);
30
+
31
+ /* Error / broken states */
32
+ --colour-broken-bg: #fee2e2;
33
+ --colour-broken-text: #7f1d1d;
34
+ --colour-broken-border: #dc2626;
35
+
36
+ /* Doc-type palette - kept in sync with mermaid classDef */
37
+ --colour-prd: #fde68a;
38
+ --colour-req: #bbf7d0;
39
+ --colour-us: #bae6fd;
40
+ --colour-ac: #e0e7ff;
41
+ --colour-tad: #fecaca;
42
+ --colour-tac: #fed7aa;
43
+ --colour-adr: #fbcfe8;
44
+ --colour-bs: #ddd6fe;
45
+ --colour-fbs: #c7d2fe;
46
+ --colour-ts: #99f6e4;
47
+ --colour-tc: #d9f99d;
48
+
49
+ /* Elevation */
50
+ --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.03);
51
+ --shadow-md: 0 4px 10px rgba(15, 23, 42, 0.05), 0 2px 4px rgba(15, 23, 42, 0.04);
52
+ --shadow-lg: 0 12px 28px rgba(15, 23, 42, 0.08), 0 4px 8px rgba(15, 23, 42, 0.04);
53
+
54
+ /* Radii */
55
+ --radius-sm: 6px;
56
+ --radius-md: 10px;
57
+ --radius-lg: 14px;
58
+
59
+ /* Transitions */
60
+ --t-fast: 120ms ease;
61
+ --t-med: 180ms ease;
62
+ }
63
+
64
+ * { box-sizing: border-box; }
65
+
66
+ html { font-size: 16px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
67
+
68
+ body {
69
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI Variable', 'Segoe UI', Roboto, 'Helvetica Neue', system-ui, sans-serif;
70
+ line-height: 1.55;
71
+ color: var(--colour-text);
72
+ background: var(--colour-bg);
73
+ max-width: 80rem;
74
+ margin: 0 auto;
75
+ padding: 0 2rem 3rem;
76
+ font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
77
+ }
78
+
79
+ /* --------------------------------------------------------------------
80
+ * Header
81
+ * -------------------------------------------------------------------- */
82
+
83
+ header {
84
+ padding: 2rem 0 1rem;
85
+ margin-bottom: 0.75rem;
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 0.35rem;
89
+ }
90
+
91
+ header h1 {
92
+ margin: 0;
93
+ font-size: 2rem;
94
+ font-weight: 700;
95
+ letter-spacing: -0.02em;
96
+ color: var(--colour-heading);
97
+ display: flex;
98
+ align-items: center;
99
+ gap: 0.75rem;
100
+ }
101
+
102
+ /* Stravica monogram alongside the project name - shared identity with
103
+ * the marketing site (stravica.ai). SVG is inlined as a data URL so no
104
+ * separate asset has to ship. */
105
+ header h1::before {
106
+ content: '';
107
+ display: inline-block;
108
+ width: 2rem;
109
+ height: 2rem;
110
+ flex-shrink: 0;
111
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Crect width='512' height='512' rx='64' fill='%23c14a3a'/%3E%3Ctext x='256' y='370' font-family='Georgia,serif' font-size='360' font-weight='600' text-anchor='middle' fill='%23f7f5f0'%3ES%3C/text%3E%3C/svg%3E");
112
+ background-repeat: no-repeat;
113
+ background-position: center;
114
+ background-size: contain;
115
+ border-radius: var(--radius-sm);
116
+ box-shadow: var(--shadow-sm);
117
+ }
118
+
119
+ .subtitle {
120
+ color: var(--colour-muted);
121
+ margin: 0;
122
+ font-size: 0.95rem;
123
+ }
124
+
125
+ /* --------------------------------------------------------------------
126
+ * Tab bar (sticky, blurred backdrop)
127
+ * -------------------------------------------------------------------- */
128
+
129
+ nav.tabs {
130
+ display: flex;
131
+ flex-wrap: wrap;
132
+ gap: 0.25rem;
133
+ padding: 0.5rem 0.5rem 0;
134
+ position: sticky;
135
+ top: 0;
136
+ z-index: 10;
137
+ background: rgba(253, 253, 253, 0.85);
138
+ backdrop-filter: saturate(180%) blur(12px);
139
+ -webkit-backdrop-filter: saturate(180%) blur(12px);
140
+ border-bottom: 1px solid var(--colour-border);
141
+ margin: 0 -0.5rem;
142
+ }
143
+
144
+ nav.tabs button {
145
+ appearance: none;
146
+ border: 1px solid transparent;
147
+ border-radius: var(--radius-md) var(--radius-md) 0 0;
148
+ background: transparent;
149
+ color: var(--colour-muted);
150
+ padding: 0.6rem 1.1rem;
151
+ font-size: 0.95rem;
152
+ font-weight: 500;
153
+ cursor: pointer;
154
+ font-family: inherit;
155
+ transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
156
+ margin-bottom: -1px;
157
+ position: relative;
158
+ }
159
+
160
+ nav.tabs button:hover {
161
+ background: var(--colour-accent-subtle);
162
+ color: var(--colour-accent-hover);
163
+ }
164
+
165
+ nav.tabs button[aria-selected="true"] {
166
+ background: var(--colour-bg);
167
+ color: var(--colour-heading);
168
+ font-weight: 600;
169
+ border-color: var(--colour-border);
170
+ border-bottom-color: var(--colour-bg);
171
+ }
172
+
173
+ nav.tabs button[aria-selected="true"]::after {
174
+ content: '';
175
+ position: absolute;
176
+ left: 0.9rem;
177
+ right: 0.9rem;
178
+ bottom: -1px;
179
+ height: 2px;
180
+ background: var(--colour-accent);
181
+ border-radius: 2px;
182
+ }
183
+
184
+ nav.tabs button:focus-visible {
185
+ outline: 2px solid var(--colour-accent);
186
+ outline-offset: 2px;
187
+ }
188
+
189
+ /* --------------------------------------------------------------------
190
+ * Panels + section headings
191
+ * -------------------------------------------------------------------- */
192
+
193
+ section[role="tabpanel"] {
194
+ padding-top: 2rem;
195
+ }
196
+
197
+ section[role="tabpanel"][hidden] {
198
+ display: none;
199
+ }
200
+
201
+ h2.tab-heading {
202
+ font-size: 1.5rem;
203
+ font-weight: 700;
204
+ letter-spacing: -0.015em;
205
+ color: var(--colour-heading);
206
+ margin: 0 0 1.25rem;
207
+ padding-bottom: 0.5rem;
208
+ border-bottom: 1px solid var(--colour-border);
209
+ position: relative;
210
+ }
211
+
212
+ h2.tab-heading::before {
213
+ content: '';
214
+ position: absolute;
215
+ left: 0;
216
+ bottom: -1px;
217
+ width: 3rem;
218
+ height: 2px;
219
+ background: var(--colour-accent);
220
+ border-radius: 2px;
221
+ }
222
+
223
+ .group-heading {
224
+ font-size: 1.1rem;
225
+ font-weight: 600;
226
+ margin-top: 2.25rem;
227
+ margin-bottom: 1rem;
228
+ color: var(--colour-heading);
229
+ text-transform: uppercase;
230
+ letter-spacing: 0.06em;
231
+ font-size: 0.8rem;
232
+ }
233
+
234
+ /* --------------------------------------------------------------------
235
+ * Overview diagram
236
+ * -------------------------------------------------------------------- */
237
+
238
+ /* --------------------------------------------------------------------
239
+ * Doc article - the rendered doc body inside a card
240
+ * -------------------------------------------------------------------- */
241
+
242
+ article.doc {
243
+ border: 1px solid var(--colour-border);
244
+ border-left-width: 5px;
245
+ padding: 1.25rem 1.5rem;
246
+ border-radius: var(--radius-md);
247
+ margin-bottom: 1.5rem;
248
+ background: var(--colour-bg);
249
+ box-shadow: var(--shadow-sm);
250
+ transition: box-shadow var(--t-med), transform var(--t-med);
251
+ }
252
+
253
+ article.doc h3 {
254
+ margin: 0 0 0.85rem;
255
+ font-size: 1.2rem;
256
+ font-weight: 600;
257
+ color: var(--colour-heading);
258
+ letter-spacing: -0.01em;
259
+ }
260
+
261
+ /* When the article is embedded inside a doc-details wrapper, the parent
262
+ * details already carries the border + shadow + radius + background +
263
+ * coloured left accent. Strip the article's own card treatment so we
264
+ * don't render a card inside a card. Also hide the article's own h3 -
265
+ * the summary line already carries the title. */
266
+ details.doc-details > article.doc {
267
+ border: none;
268
+ border-radius: 0;
269
+ background: transparent;
270
+ box-shadow: none;
271
+ margin-bottom: 0;
272
+ }
273
+
274
+ details.doc-details > article.doc > h3 {
275
+ display: none;
276
+ }
277
+
278
+ article.doc-prd { border-left-color: var(--colour-prd); }
279
+ article.doc-req { border-left-color: var(--colour-req); }
280
+ article.doc-us { border-left-color: var(--colour-us); }
281
+ article.doc-tad { border-left-color: var(--colour-tad); }
282
+ article.doc-tac { border-left-color: var(--colour-tac); }
283
+ article.doc-adr { border-left-color: var(--colour-adr); }
284
+ article.doc-bs { border-left-color: var(--colour-bs); }
285
+ article.doc-fbs { border-left-color: var(--colour-fbs); }
286
+ article.doc-ts { border-left-color: var(--colour-ts); }
287
+
288
+ article.doc p { margin: 0.45rem 0; }
289
+ article.doc h4 { margin: 1.1rem 0 0.45rem; font-size: 1rem; font-weight: 600; color: var(--colour-heading); }
290
+ article.doc h5 { margin: 0.6rem 0 0.3rem; font-size: 0.925rem; font-weight: 600; color: var(--colour-heading); }
291
+
292
+ .field-list { margin: 0.85rem 0; }
293
+ .field-list ul { margin: 0.3rem 0; padding-left: 1.5rem; }
294
+ .field-list ul li { margin: 0.2rem 0; }
295
+ .field-list dl dt { font-weight: 600; margin-top: 0.5rem; color: var(--colour-heading); }
296
+ .field-list dl dd { margin-left: 0; margin-bottom: 0.35rem; }
297
+
298
+ /* --------------------------------------------------------------------
299
+ * Acceptance criteria list (inside a US)
300
+ * -------------------------------------------------------------------- */
301
+
302
+ .ac-list { list-style: none; padding-left: 0; margin: 0; }
303
+
304
+ .ac-list .ac-item {
305
+ background: transparent;
306
+ border: none;
307
+ border-left: 3px solid var(--colour-ac);
308
+ border-radius: 0;
309
+ padding: 0.5rem 0.9rem;
310
+ margin-bottom: 0.5rem;
311
+ box-shadow: none;
312
+ }
313
+
314
+ .ac-list .ac-item:last-child {
315
+ margin-bottom: 0;
316
+ }
317
+
318
+ .ac-list .ac-item p { margin: 0.3rem 0; }
319
+ .ac-list .ac-gwt p { margin: 0.2rem 0; }
320
+ .ac-meta { color: var(--colour-muted); font-size: 0.875rem; }
321
+
322
+ /* AC pills (used in FBS -> AC nav on the Build tab) */
323
+ .ac-pills {
324
+ display: flex;
325
+ flex-wrap: wrap;
326
+ gap: 0.4rem;
327
+ margin: 0.6rem 0 0.85rem;
328
+ }
329
+
330
+ .ac-pills .ac-pill {
331
+ display: inline-block;
332
+ padding: 0.22rem 0.7rem;
333
+ border-radius: 999px;
334
+ background: var(--colour-ac);
335
+ color: #3730a3;
336
+ text-decoration: none;
337
+ font-size: 0.85rem;
338
+ font-weight: 500;
339
+ border: 1px solid #c7d2fe;
340
+ transition: background var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
341
+ }
342
+
343
+ .ac-pills .ac-pill:hover {
344
+ background: #c7d2fe;
345
+ box-shadow: var(--shadow-sm);
346
+ transform: translateY(-1px);
347
+ }
348
+
349
+ .ac-resolved {
350
+ background: transparent;
351
+ border: none;
352
+ border-left: 3px solid var(--colour-ac);
353
+ border-radius: 0;
354
+ padding: 0.5rem 0.9rem;
355
+ margin-bottom: 0.5rem;
356
+ }
357
+
358
+ .ac-resolved.broken {
359
+ border-left-color: var(--colour-broken-border);
360
+ background: var(--colour-broken-bg);
361
+ }
362
+
363
+ .tc {
364
+ background: transparent;
365
+ border: none;
366
+ border-left: 3px solid var(--colour-ac);
367
+ border-radius: 0;
368
+ padding: 0.5rem 0.9rem;
369
+ margin-bottom: 0.5rem;
370
+ }
371
+
372
+ /* --------------------------------------------------------------------
373
+ * Subdiagram (per-REQ, shown inside an expanded REQ)
374
+ * -------------------------------------------------------------------- */
375
+
376
+ .subdiagram {
377
+ margin: 1.25rem 0;
378
+ padding: 0.85rem;
379
+ background: var(--colour-surface);
380
+ border: 1px solid var(--colour-border);
381
+ border-radius: var(--radius-md);
382
+ }
383
+
384
+ pre.mermaid {
385
+ background: transparent;
386
+ border: none;
387
+ border-radius: var(--radius-sm);
388
+ padding: 0;
389
+ overflow-x: auto;
390
+ font-size: 0.875rem;
391
+ margin: 0;
392
+ }
393
+
394
+ /* --------------------------------------------------------------------
395
+ * Details drill-down wrappers (REQ / US / TAC / ADR / FBS / TS)
396
+ * -------------------------------------------------------------------- */
397
+
398
+ details.doc-details {
399
+ border: 1px solid var(--colour-border);
400
+ border-radius: var(--radius-md);
401
+ margin-bottom: 0.85rem;
402
+ background: var(--colour-bg);
403
+ box-shadow: var(--shadow-sm);
404
+ transition: box-shadow var(--t-med), border-color var(--t-med);
405
+ }
406
+
407
+ details.doc-details:hover {
408
+ box-shadow: var(--shadow-md);
409
+ border-color: var(--colour-border-strong);
410
+ }
411
+
412
+ details.doc-details[open] {
413
+ box-shadow: var(--shadow-md);
414
+ }
415
+
416
+ details.doc-details > summary {
417
+ cursor: pointer;
418
+ padding: 0.75rem 1rem;
419
+ font-weight: 500;
420
+ color: var(--colour-heading);
421
+ list-style: none;
422
+ display: flex;
423
+ align-items: center;
424
+ gap: 0.6rem;
425
+ border-radius: var(--radius-md);
426
+ transition: background var(--t-fast);
427
+ }
428
+
429
+ details.doc-details > summary > .summary-label {
430
+ flex: 1 1 auto;
431
+ min-width: 0;
432
+ overflow: hidden;
433
+ text-overflow: ellipsis;
434
+ white-space: nowrap;
435
+ }
436
+
437
+ details.doc-details > summary > .status {
438
+ flex-shrink: 0;
439
+ margin-left: auto;
440
+ }
441
+
442
+ details.doc-details > summary:hover {
443
+ background: var(--colour-surface);
444
+ }
445
+
446
+ details.doc-details > summary::-webkit-details-marker { display: none; }
447
+
448
+ /* Custom chevron */
449
+ details.doc-details > summary::before {
450
+ content: '';
451
+ display: inline-block;
452
+ width: 0.6rem;
453
+ height: 0.6rem;
454
+ border-right: 2px solid var(--colour-muted);
455
+ border-bottom: 2px solid var(--colour-muted);
456
+ transform: rotate(-45deg);
457
+ transition: transform var(--t-fast);
458
+ flex-shrink: 0;
459
+ margin-right: 0.15rem;
460
+ }
461
+
462
+ details.doc-details[open] > summary::before {
463
+ transform: rotate(45deg);
464
+ }
465
+
466
+ details.doc-details[open] > summary {
467
+ border-radius: var(--radius-md) var(--radius-md) 0 0;
468
+ border-bottom: 1px solid var(--colour-border);
469
+ }
470
+
471
+ details.doc-details > article,
472
+ details.doc-details > section,
473
+ details.doc-details > .req-body,
474
+ details.doc-details > .us-body {
475
+ padding: 1rem 1.25rem;
476
+ }
477
+
478
+ details.doc-details.doc-req-wrap { border-left: 4px solid var(--colour-req); }
479
+ details.doc-details.doc-us-wrap { border-left: 4px solid var(--colour-us); }
480
+ details.doc-details.doc-tac-wrap { border-left: 4px solid var(--colour-tac); }
481
+ details.doc-details.doc-adr-wrap { border-left: 4px solid var(--colour-adr); }
482
+ details.doc-details.doc-fbs-wrap { border-left: 4px solid var(--colour-fbs); }
483
+ details.doc-details.doc-ts-wrap { border-left: 4px solid var(--colour-ts); }
484
+
485
+ .nested-details {
486
+ margin: 0 1rem 1rem;
487
+ }
488
+
489
+ .nested-details > h4 {
490
+ margin: 0.75rem 0 0.6rem;
491
+ color: var(--colour-muted);
492
+ font-size: 0.85rem;
493
+ font-weight: 600;
494
+ text-transform: uppercase;
495
+ letter-spacing: 0.04em;
496
+ }
497
+
498
+ /* --------------------------------------------------------------------
499
+ * Nested details: strip the outer-card treatment so a REQ card
500
+ * expanded to show its US children doesn't render "card inside card
501
+ * inside card". Keep the coloured left accent so hierarchy is still
502
+ * visible, drop border/radius/shadow/background on the other sides.
503
+ * -------------------------------------------------------------------- */
504
+
505
+ details.doc-details details.doc-details {
506
+ border-top-color: transparent;
507
+ border-right-color: transparent;
508
+ border-bottom-color: transparent;
509
+ border-radius: 0;
510
+ background: transparent;
511
+ box-shadow: none;
512
+ margin-bottom: 0.4rem;
513
+ }
514
+
515
+ details.doc-details details.doc-details:hover,
516
+ details.doc-details details.doc-details[open] {
517
+ box-shadow: none;
518
+ }
519
+
520
+ details.doc-details details.doc-details:hover {
521
+ border-top-color: transparent;
522
+ border-right-color: transparent;
523
+ border-bottom-color: transparent;
524
+ }
525
+
526
+ details.doc-details details.doc-details > summary {
527
+ padding: 0.5rem 0.85rem;
528
+ border-radius: 0;
529
+ }
530
+
531
+ details.doc-details details.doc-details > summary:hover {
532
+ background: var(--colour-surface);
533
+ }
534
+
535
+ details.doc-details details.doc-details[open] > summary {
536
+ border-bottom: 1px dashed var(--colour-border);
537
+ border-radius: 0;
538
+ }
539
+
540
+ details.doc-details details.doc-details > article,
541
+ details.doc-details details.doc-details > section,
542
+ details.doc-details details.doc-details > .req-body,
543
+ details.doc-details details.doc-details > .us-body {
544
+ padding: 0.5rem 0.85rem 0.75rem;
545
+ }
546
+
547
+ /* Raw-JSON disclosure (dev-facing, quiet) */
548
+ details.raw-json {
549
+ margin-top: 1rem;
550
+ border-top: 1px dashed var(--colour-border);
551
+ padding-top: 0.75rem;
552
+ }
553
+
554
+ details.raw-json summary {
555
+ cursor: pointer;
556
+ color: var(--colour-muted);
557
+ font-size: 0.8125rem;
558
+ padding: 0.15rem 0;
559
+ }
560
+
561
+ details.raw-json summary:hover { color: var(--colour-accent); }
562
+
563
+ details.raw-json pre {
564
+ background: var(--colour-surface-2);
565
+ padding: 0.85rem 1rem;
566
+ border-radius: var(--radius-sm);
567
+ overflow-x: auto;
568
+ font-size: 0.8rem;
569
+ border: 1px solid var(--colour-border);
570
+ margin-top: 0.5rem;
571
+ }
572
+
573
+ /* --------------------------------------------------------------------
574
+ * Links, code, status pills, broken states
575
+ * -------------------------------------------------------------------- */
576
+
577
+ a {
578
+ color: var(--colour-link);
579
+ text-decoration: none;
580
+ transition: color var(--t-fast);
581
+ }
582
+
583
+ a:hover {
584
+ color: var(--colour-accent-hover);
585
+ text-decoration: underline;
586
+ text-underline-offset: 3px;
587
+ }
588
+
589
+ code {
590
+ background: var(--colour-surface-2);
591
+ padding: 0.12rem 0.35rem;
592
+ border-radius: 4px;
593
+ font-size: 0.875em;
594
+ font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
595
+ color: #3730a3;
596
+ }
597
+
598
+ /* Status pill (compact, coloured by status) */
599
+ .status {
600
+ display: inline-block;
601
+ padding: 0.15rem 0.6rem;
602
+ border-radius: 999px;
603
+ font-size: 0.75rem;
604
+ font-weight: 600;
605
+ text-transform: uppercase;
606
+ letter-spacing: 0.04em;
607
+ border: 1px solid transparent;
608
+ }
609
+
610
+ .status.notStarted {
611
+ color: var(--colour-muted);
612
+ background: var(--colour-surface-2);
613
+ border-color: var(--colour-border);
614
+ }
615
+
616
+ .status.inProgress {
617
+ color: #0c4a6e;
618
+ background: #e0f2fe;
619
+ border-color: #bae6fd;
620
+ }
621
+
622
+ .status.complete {
623
+ color: #065f46;
624
+ background: #d1fae5;
625
+ border-color: #a7f3d0;
626
+ }
627
+
628
+ .status.verified {
629
+ color: #14532d;
630
+ background: #bbf7d0;
631
+ border-color: #86efac;
632
+ }
633
+
634
+ .status.blocked {
635
+ color: var(--colour-broken-text);
636
+ background: var(--colour-broken-bg);
637
+ border-color: var(--colour-broken-border);
638
+ }
639
+
640
+ .status.draft,
641
+ .status.review,
642
+ .status.needsRevision,
643
+ .status.approved,
644
+ .status.superseded,
645
+ .status.deprecated,
646
+ .status.proposed,
647
+ .status.accepted {
648
+ color: var(--colour-muted);
649
+ background: var(--colour-surface-2);
650
+ border-color: var(--colour-border);
651
+ }
652
+
653
+ .status.approved,
654
+ .status.accepted { color: #065f46; background: #d1fae5; border-color: #a7f3d0; }
655
+ .status.deprecated,
656
+ .status.superseded { color: var(--colour-muted); background: var(--colour-surface); border-color: var(--colour-border); }
657
+
658
+ /* Broken doc / tree error banner */
659
+ .broken {
660
+ background: var(--colour-broken-bg);
661
+ border: 1px solid var(--colour-broken-border);
662
+ color: var(--colour-broken-text);
663
+ padding: 0.65rem 0.9rem;
664
+ border-radius: var(--radius-sm);
665
+ margin-bottom: 0.85rem;
666
+ }
667
+
668
+ .broken ul {
669
+ margin: 0.3rem 0 0 1.35rem;
670
+ }
671
+
672
+ .broken-doc {
673
+ border-left-color: var(--colour-broken-border);
674
+ }
675
+
676
+ .tree-errors {
677
+ background: var(--colour-broken-bg);
678
+ border: 1px solid var(--colour-broken-border);
679
+ color: var(--colour-broken-text);
680
+ padding: 1.1rem 1.35rem;
681
+ border-radius: var(--radius-md);
682
+ margin-bottom: 2rem;
683
+ box-shadow: var(--shadow-sm);
684
+ }
685
+
686
+ .tree-errors h2 {
687
+ margin: 0 0 0.5rem;
688
+ font-size: 1.15rem;
689
+ font-weight: 700;
690
+ color: var(--colour-broken-text);
691
+ border: none;
692
+ padding: 0;
693
+ }
694
+
695
+ /* --------------------------------------------------------------------
696
+ * Footer
697
+ * -------------------------------------------------------------------- */
698
+
699
+ footer {
700
+ border-top: 1px solid var(--colour-border);
701
+ padding-top: 1.25rem;
702
+ margin-top: 3rem;
703
+ color: var(--colour-muted);
704
+ font-size: 0.85rem;
705
+ }
706
+
707
+ /* --------------------------------------------------------------------
708
+ * Print
709
+ * -------------------------------------------------------------------- */
710
+
711
+ @media print {
712
+ body { max-width: none; padding: 0; }
713
+ nav.tabs { display: none; }
714
+ section[role="tabpanel"][hidden] { display: block !important; }
715
+ pre.mermaid { page-break-inside: avoid; }
716
+ article.doc { page-break-inside: avoid; box-shadow: none; }
717
+ details.doc-details { break-inside: avoid; box-shadow: none; }
718
+ details.doc-details[open] > summary { border: none; }
719
+ header h1::before { display: none; }
720
+ }
721
+
722
+ /* --------------------------------------------------------------------
723
+ * Responsive
724
+ * -------------------------------------------------------------------- */
725
+
726
+ @media (max-width: 720px) {
727
+ body { padding: 0 1rem 2rem; }
728
+ header h1 { font-size: 1.55rem; }
729
+ nav.tabs button { padding: 0.5rem 0.8rem; font-size: 0.9rem; }
730
+ article.doc { padding: 1rem 1.15rem; }
731
+ details.doc-details > article,
732
+ details.doc-details > section,
733
+ details.doc-details > .req-body,
734
+ details.doc-details > .us-body { padding: 0.75rem 1rem; }
735
+ }