@giamme/forge 0.0.0-stage → 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 (127) hide show
  1. package/CHANGELOG.md +181 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1854 -2
  4. package/SKILL.md +122 -0
  5. package/VERSION +1 -0
  6. package/forge +74 -0
  7. package/package.json +26 -4
  8. package/references/dataset.md +329 -0
  9. package/references/decompose.md +667 -0
  10. package/references/fractal-dashboard.md +21 -0
  11. package/references/fractal.md +307 -0
  12. package/references/harnesses.md +353 -0
  13. package/references/jev.md +865 -0
  14. package/references/memory.md +228 -0
  15. package/references/planning.md +42 -0
  16. package/references/ripwire.md +47 -0
  17. package/references/runtime.md +64 -0
  18. package/references/solo.md +113 -0
  19. package/references/ui.md +112 -0
  20. package/registry.tsv +81 -0
  21. package/scripts/forge-artifact.sh +78 -0
  22. package/scripts/forge-contract.py +430 -0
  23. package/scripts/forge-dataset.py +6 -0
  24. package/scripts/forge-dispatch.sh +665 -0
  25. package/scripts/forge-fail-first.py +195 -0
  26. package/scripts/forge-fractal-dispatch.sh +4 -0
  27. package/scripts/forge-fractal-options.sh +54 -0
  28. package/scripts/forge-fractal.py +6 -0
  29. package/scripts/forge-guard.py +266 -0
  30. package/scripts/forge-install-fractal.sh +4 -0
  31. package/scripts/forge-install-ripwire.sh +52 -0
  32. package/scripts/forge-install.sh +135 -0
  33. package/scripts/forge-jev-options.sh +259 -0
  34. package/scripts/forge-jev.py +6 -0
  35. package/scripts/forge-lib-plans.sh +785 -0
  36. package/scripts/forge-lib-review.sh +494 -0
  37. package/scripts/forge-lib-task.sh +302 -0
  38. package/scripts/forge-lib-verify.sh +30 -0
  39. package/scripts/forge-memory.sh +575 -0
  40. package/scripts/forge-metrics.sh +39 -0
  41. package/scripts/forge-parallel-options.sh +76 -0
  42. package/scripts/forge-parallel.sh +1717 -0
  43. package/scripts/forge-plan-check.py +118 -0
  44. package/scripts/forge-prompt.py +45 -0
  45. package/scripts/forge-ripwire.py +136 -0
  46. package/scripts/forge-route.py +344 -0
  47. package/scripts/forge-runtime.py +533 -0
  48. package/scripts/forge-schedule.py +312 -0
  49. package/scripts/forge-shadow.py +305 -0
  50. package/scripts/forge-solo.sh +347 -0
  51. package/scripts/forge-ui-options.sh +42 -0
  52. package/scripts/forge-ui.py +435 -0
  53. package/scripts/forge-update.sh +71 -0
  54. package/scripts/forge-verify-coverage.py +956 -0
  55. package/scripts/forge-version.py +198 -0
  56. package/scripts/forge_dataset/__init__.py +439 -0
  57. package/scripts/forge_dataset/capture.py +330 -0
  58. package/scripts/forge_dataset/checks.py +109 -0
  59. package/scripts/forge_dataset/cli.py +233 -0
  60. package/scripts/forge_dataset/export.py +1009 -0
  61. package/scripts/forge_dataset/harvest.py +716 -0
  62. package/scripts/forge_dataset/importer.py +412 -0
  63. package/scripts/forge_dataset/outcomes.py +275 -0
  64. package/scripts/forge_dataset/routing.py +278 -0
  65. package/scripts/forge_fractal/__init__.py +83 -0
  66. package/scripts/forge_fractal/bridge.py +46 -0
  67. package/scripts/forge_fractal/cli.py +202 -0
  68. package/scripts/forge_fractal/dashboard.css +138 -0
  69. package/scripts/forge_fractal/dashboard.html +41 -0
  70. package/scripts/forge_fractal/dashboard.js +687 -0
  71. package/scripts/forge_fractal/decomposition.py +262 -0
  72. package/scripts/forge_fractal/execution.py +659 -0
  73. package/scripts/forge_fractal/inspection.py +261 -0
  74. package/scripts/forge_fractal/install.py +158 -0
  75. package/scripts/forge_fractal/invocation.py +94 -0
  76. package/scripts/forge_fractal/pipeline.py +124 -0
  77. package/scripts/forge_fractal/selection.py +179 -0
  78. package/scripts/forge_jev/__init__.py +376 -0
  79. package/scripts/forge_jev/backtest.py +322 -0
  80. package/scripts/forge_jev/cli.py +980 -0
  81. package/scripts/forge_jev/client.py +418 -0
  82. package/scripts/forge_jev/corpus.py +156 -0
  83. package/scripts/forge_jev/coupling.py +244 -0
  84. package/scripts/forge_jev/features.py +24 -0
  85. package/scripts/forge_jev/gates.py +100 -0
  86. package/scripts/forge_jev/memory.py +163 -0
  87. package/scripts/forge_jev/outcome.py +49 -0
  88. package/scripts/forge_jev/predict.py +204 -0
  89. package/scripts/forge_jev/questions.py +661 -0
  90. package/scripts/forge_jev/review.py +73 -0
  91. package/scripts/forge_jev/routing.py +271 -0
  92. package/scripts/forge_jev/subset.py +123 -0
  93. package/scripts/forge_jev/verify.py +453 -0
  94. package/scripts/forge_registry.py +140 -0
  95. package/ui/README.md +287 -0
  96. package/ui/THIRD_PARTY_NOTICES.md +69 -0
  97. package/ui/docs/api.md +888 -0
  98. package/ui/forge_ui/__init__.py +20 -0
  99. package/ui/forge_ui/__main__.py +135 -0
  100. package/ui/forge_ui/diffs.py +454 -0
  101. package/ui/forge_ui/executions.py +436 -0
  102. package/ui/forge_ui/export.py +204 -0
  103. package/ui/forge_ui/findings.py +132 -0
  104. package/ui/forge_ui/fractal.py +583 -0
  105. package/ui/forge_ui/models.py +216 -0
  106. package/ui/forge_ui/reader.py +1336 -0
  107. package/ui/forge_ui/server.py +303 -0
  108. package/ui/forge_ui/static/app.js +924 -0
  109. package/ui/forge_ui/static/cloud3d.js +646 -0
  110. package/ui/forge_ui/static/cloudmodel.js +375 -0
  111. package/ui/forge_ui/static/cloudui.js +394 -0
  112. package/ui/forge_ui/static/diffview.js +216 -0
  113. package/ui/forge_ui/static/favicon.svg +1 -0
  114. package/ui/forge_ui/static/files.js +776 -0
  115. package/ui/forge_ui/static/gantt.js +97 -0
  116. package/ui/forge_ui/static/graph.js +266 -0
  117. package/ui/forge_ui/static/index.html +55 -0
  118. package/ui/forge_ui/static/iso.js +765 -0
  119. package/ui/forge_ui/static/leaderboard.js +315 -0
  120. package/ui/forge_ui/static/map3d.js +45 -0
  121. package/ui/forge_ui/static/modelstats.js +249 -0
  122. package/ui/forge_ui/static/notify.js +179 -0
  123. package/ui/forge_ui/static/panel.js +526 -0
  124. package/ui/forge_ui/static/runmodel.js +651 -0
  125. package/ui/forge_ui/static/scene3d.js +996 -0
  126. package/ui/forge_ui/static/search.js +119 -0
  127. package/ui/forge_ui/static/style.css +618 -0
@@ -0,0 +1,618 @@
1
+ :root {
2
+ color-scheme: light dark;
3
+ --bg: #f5f6f8;
4
+ --surface: #fff;
5
+ --subtle: #eef1f5;
6
+ --text: #202936;
7
+ --muted: #596575;
8
+ --line: #d8dee7;
9
+ --accent: #245bb2;
10
+ --selected: #eaf1ff;
11
+ --warning-bg: #fff3d8;
12
+ --warning-text: #714a00;
13
+ --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
14
+ font: 14px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
15
+ }
16
+ @media (prefers-color-scheme: dark) {
17
+ :root {
18
+ --bg: #15191f;
19
+ --surface: #1c222b;
20
+ --subtle: #242c37;
21
+ --text: #e1e7ef;
22
+ --muted: #a9b5c5;
23
+ --line: #384353;
24
+ --accent: #97bdff;
25
+ --selected: #263b58;
26
+ --warning-bg: #3a2e17;
27
+ --warning-text: #f4d28a;
28
+ }
29
+ }
30
+ .st-merged { --st: #23783d; }
31
+ .st-pass { --st: #23783d; }
32
+ .st-running { --st: #245bb2; }
33
+ .st-pending { --st: #596575; }
34
+ .st-fail { --st: #ae2b36; }
35
+ .st-error { --st: #ae2b36; }
36
+ .st-infra { --st: #985008; }
37
+ .st-timeout { --st: #985008; }
38
+ .st-unknown { --st: #725389; }
39
+ .st-invalidated { --st: #725389; }
40
+ .st-blocked { --st: #725389; }
41
+ .st-interrupted { --st: #725389; }
42
+ .st-nochanges { --st: #1f6f78; }
43
+ .st-conflict { --st: #a2336f; }
44
+ @media (prefers-color-scheme: dark) {
45
+ .st-merged, .st-pass { --st: #85d59b; }
46
+ .st-running { --st: #97bdff; }
47
+ .st-pending { --st: #b2bdcb; }
48
+ .st-fail, .st-error { --st: #ff9da5; }
49
+ .st-infra, .st-timeout { --st: #f3bb77; }
50
+ .st-unknown, .st-invalidated, .st-blocked, .st-interrupted { --st: #c9a7e4; }
51
+ .st-nochanges { --st: #86d0d8; }
52
+ .st-conflict { --st: #f0a3cb; }
53
+ }
54
+ * { box-sizing: border-box; }
55
+ body { margin: 0; background: var(--bg); color: var(--text); }
56
+ a { color: var(--accent); text-underline-offset: 3px; }
57
+ a:hover { text-decoration-thickness: 2px; }
58
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
59
+ ::selection { background: var(--selected); color: var(--text); }
60
+ input { accent-color: var(--accent); caret-color: var(--accent); }
61
+ * { scrollbar-color: var(--muted) var(--subtle); scrollbar-width: thin; }
62
+ h1, h2, p { margin: 0; }
63
+ h1 { font-size: 1.2rem; }
64
+ h2 { font-size: 1.05rem; font-weight: 650; margin-bottom: 12px; overflow-wrap: anywhere; }
65
+ .muted, .empty { color: var(--muted); }
66
+ .mono, pre, .chip { font-family: var(--mono); font-size: .85rem; }
67
+ .topbar { display: flex; align-items: center; gap: 20px; padding: 14px 22px; border-bottom: 1px solid var(--line); background: var(--surface); }
68
+ .brand { color: var(--text); font-weight: 750; font-size: 1.1rem; text-decoration: none; white-space: nowrap; }
69
+ .refresh-control { margin-left: auto; display: flex; align-items: center; gap: 6px; cursor: pointer; white-space: nowrap; }
70
+ #errors { padding: 8px 22px; background: var(--warning-bg); color: var(--warning-text); overflow-wrap: anywhere; }
71
+ .layout { display: grid; grid-template-columns: 300px minmax(0, 1fr); min-height: calc(100vh - 56px); }
72
+ .sidebar { min-width: 0; background: var(--surface); border-right: 1px solid var(--line); }
73
+ .sidebar-heading { padding: 20px 18px 10px; display: flex; justify-content: space-between; align-items: center; }
74
+ .filter-label { display: block; padding: 0 18px 6px; color: var(--muted); font-size: .8rem; }
75
+ #filter { display: block; width: calc(100% - 36px); margin: 0 18px 18px; padding: 9px 10px; border: 1px solid var(--line); border-radius: 5px; background: var(--bg); color: var(--text); font: inherit; }
76
+ #filter::placeholder { color: var(--muted); }
77
+ #run-list { max-height: calc(100vh - 220px); overflow-y: auto; }
78
+ .run-item { display: flex; flex-direction: column; gap: 4px; padding: 15px 18px; border-top: 1px solid var(--line); text-decoration: none; color: var(--text); min-width: 0; }
79
+ .run-item:hover { background: var(--subtle); }
80
+ .run-item.selected { background: var(--selected); box-shadow: inset 3px 0 var(--accent); }
81
+ .run-goal { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
82
+ .run-item .mono { overflow-wrap: anywhere; }
83
+ .repo { font-size: .9rem; }
84
+ .tag { align-self: flex-start; border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; color: var(--muted); font-size: .73rem; line-height: 1.5; }
85
+ .updated, .verification { font-size: .8rem; }
86
+ .chips { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 5px; }
87
+ .chip { display: inline-block; border: 1px solid currentColor; color: var(--st, var(--muted)); border-radius: 4px; padding: 1px 5px; white-space: nowrap; font-size: .73rem; font-weight: 600; line-height: 1.5; }
88
+ .verification { margin-top: 5px; color: var(--muted); }
89
+ main { min-width: 0; padding: 24px; }
90
+ main > section { margin-bottom: 28px; }
91
+ .run-header > h2 { font-size: 1.5rem; line-height: 1.3; white-space: pre-wrap; margin-bottom: 20px; }
92
+ .fields { display: grid; grid-template-columns: minmax(100px, 140px) minmax(0, 1fr); gap: 6px 16px; margin: 0 0 18px; }
93
+ dt { color: var(--muted); font-size: .85rem; }
94
+ dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; min-width: 0; }
95
+ details { border-top: 1px solid var(--line); padding: 9px 0; }
96
+ summary { cursor: pointer; font-weight: 550; overflow-wrap: anywhere; }
97
+ summary:hover { color: var(--accent); }
98
+ pre { margin: 10px 0 0; padding: 12px; background: var(--subtle); border-radius: 4px; max-height: 320px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 4; line-height: 1.6; }
99
+ .table-scroll { overflow: auto; max-width: 100%; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); }
100
+ table { width: 100%; border-collapse: collapse; text-align: left; font-variant-numeric: tabular-nums; }
101
+ th { font-size: .78rem; font-weight: 650; background: var(--subtle); white-space: nowrap; }
102
+ th, td { padding: 9px 11px; vertical-align: top; border-bottom: 1px solid var(--line); }
103
+ tbody tr:last-child td { border-bottom: 0; }
104
+ td { max-width: 340px; min-width: 60px; overflow-wrap: anywhere; font-size: .85rem; }
105
+ td:nth-child(2) { min-width: 160px; }
106
+ td pre { margin: 0; min-width: 170px; max-height: 180px; }
107
+ tbody tr:hover { background: var(--subtle); }
108
+ tr.selected { background: var(--selected); }
109
+ .candidates { display: flex; flex-direction: column; gap: 4px; min-width: 160px; }
110
+ .chosen { font-weight: 750; color: var(--accent); }
111
+ .chosen::before { content: 'Chosen: '; }
112
+ .graph { overflow: auto; max-width: 100%; padding: 8px 0; }
113
+ .graph svg { display: block; }
114
+ .task-panel { border-top: 2px solid var(--accent); padding-top: 20px; }
115
+ .task-panel > h2 { font-size: 1.25rem; margin-top: 10px; }
116
+ .task-panel section { margin: 24px 0; }
117
+ .close-task { display: inline-block; font-size: .85rem; }
118
+ .empty { padding: 18px; overflow-wrap: anywhere; }
119
+ .empty p + p { margin-top: 12px; }
120
+ .st-none { --st: #8a929e; }
121
+ .st-accepted { --st: #1f6f78; }
122
+ @media (prefers-color-scheme: dark) {
123
+ .st-none { --st: #8f99a8; }
124
+ .st-accepted { --st: #86d0d8; }
125
+ }
126
+ .visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
127
+ .top-link { white-space: nowrap; font-size: .9rem; }
128
+ button, select { font: inherit; color: var(--text); }
129
+ select, .filters input[type=search] { padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--bg); }
130
+ button { padding: 5px 10px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); cursor: pointer; }
131
+ button:hover:not(:disabled) { border-color: var(--accent); }
132
+ button:disabled { opacity: .5; cursor: default; }
133
+ code { font-family: var(--mono); font-size: .8rem; }
134
+
135
+ /* 2D dependency graph (graph.js): colours by class, the page CSP refuses style attributes */
136
+ .fg-box { fill: var(--st, #888); fill-opacity: .12; stroke: var(--st, #888); }
137
+ .fg-bar { fill: var(--st, #888); }
138
+ .fg-verdict { fill: currentColor; }
139
+ .fg-verdict.fg-pass { fill: var(--st, #888); }
140
+ .fg-empty { color: var(--muted); padding: 12px 0; }
141
+
142
+ /* the stage: the 3D canvas and its colours (iso.js reads --stage-bg, --stage-accent and every --st) */
143
+ .stage-slot { --stage-bg: #e9eaea; --stage-accent: #d9730d; position: relative; }
144
+ @media (prefers-color-scheme: dark) { .stage-slot { --stage-bg: #121314; --stage-accent: #ff9d3c; } }
145
+ .stage-slot.stage-on, .stage-slot.stage-loading { height: clamp(420px, 64vh, 780px); border-radius: 10px; overflow: hidden; background: var(--stage-bg); border: 1px solid var(--line); }
146
+ .stage-slot.map.stage-on, .stage-slot.map.stage-loading { height: clamp(460px, 72vh, 900px); }
147
+ .stage { position: absolute; inset: 0; }
148
+ .stage-canvas { display: block; width: 100%; height: 100%; touch-action: none; outline: none; }
149
+ .stage-canvas.pointing { cursor: pointer; }
150
+ .stage-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
151
+ .stage-probe { position: absolute; width: 0; height: 0; overflow: hidden; visibility: hidden; }
152
+ .stage-note { margin: 8px 0 0; font-size: .85rem; }
153
+ .stage-slot.stage-loading::after { content: 'Loading the 3D view…'; position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); letter-spacing: .08em; text-transform: uppercase; font-size: .78rem; }
154
+ .stage-tip { position: absolute; left: 0; top: 0; z-index: 3; max-width: 300px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--text); box-shadow: 0 6px 24px rgba(0, 0, 0, .25); pointer-events: none; font-size: .82rem; }
155
+ .stage-tip-meta { color: var(--muted); font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; }
156
+ .stage-tip-title { font-weight: 650; overflow-wrap: anywhere; }
157
+ .stage-tip-body { font-family: var(--mono); font-size: .76rem; overflow-wrap: anywhere; }
158
+ .stage-tip-foot { color: var(--muted); font-size: .74rem; margin-top: 3px; }
159
+
160
+ /* the map of every run */
161
+ .map-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
162
+ .map-head .push { margin-left: auto; }
163
+ .filters { display: flex; flex-wrap: wrap; align-items: end; gap: 8px 12px; margin-bottom: 12px; }
164
+ .filter { display: flex; flex-direction: column; gap: 2px; font-size: .78rem; color: var(--muted); }
165
+ .filter.check { flex-direction: row; align-items: center; gap: 4px; color: var(--text); font-size: .85rem; padding-bottom: 5px; }
166
+ .map-cards:empty { display: none; }
167
+ .map-repo { margin: 18px 0; }
168
+ .map-repo h3 { font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin: 0 0 8px; }
169
+ .map-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
170
+ .map-card { display: flex; flex-direction: column; gap: 4px; padding: 12px; border: 1px solid var(--line); border-left: 4px solid var(--st, var(--line)); border-radius: 8px; background: var(--surface); color: var(--text); text-decoration: none; min-width: 0; }
171
+ .map-card:hover { border-color: var(--accent); }
172
+ .map-card strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
173
+ .map-card.dim { opacity: .35; }
174
+ .map-card .muted { font-size: .8rem; }
175
+ .leds { display: flex; flex-wrap: wrap; gap: 3px; }
176
+ .led { width: 8px; height: 8px; border-radius: 2px; background: var(--st, var(--muted)); }
177
+
178
+ /* a run: header, toolbar, stage beside the inspector, concurrency strip, task table */
179
+ .run-header > h2 { margin-bottom: 8px; }
180
+ .run-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-bottom: 10px; }
181
+ .run-meta .chips { margin-top: 0; }
182
+ .run-toolbar { display: flex; flex-wrap: wrap; align-items: end; gap: 10px 18px; margin-bottom: 12px; }
183
+ .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 7px; overflow: hidden; align-self: end; }
184
+ .seg button { border: 0; border-radius: 0; background: var(--surface); padding: 6px 12px; }
185
+ .seg button + button { border-left: 1px solid var(--line); }
186
+ .seg button[aria-pressed=true] { background: var(--selected); color: var(--accent); font-weight: 650; }
187
+ .overlays { display: flex; flex-wrap: wrap; align-items: end; gap: 8px 12px; }
188
+ .replay { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
189
+ .replay[hidden] { display: none; }
190
+ .replay input[type=range] { width: min(260px, 40vw); accent-color: var(--accent); }
191
+ .stage-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 400px); gap: 16px; align-items: start; }
192
+ .stage-col { min-width: 0; }
193
+ .inspector { min-width: 0; max-height: clamp(420px, 64vh, 780px); overflow: auto; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); position: relative; }
194
+ .inspector:focus { outline: none; }
195
+ .strip-wrap { margin-top: 10px; overflow-x: auto; }
196
+ .strip-wrap[hidden], .graph[hidden] { display: none; }
197
+ .run-tasks h2 { margin-top: 6px; }
198
+
199
+ /* the inspector (panel.js) */
200
+ .insp-head { margin-bottom: 12px; }
201
+ .insp-head h2 { font-size: 1.1rem; margin: 2px 0 4px; }
202
+ .insp-kind { color: var(--muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; }
203
+ .insp-close { position: absolute; right: 14px; top: 12px; font-size: .82rem; }
204
+ .insp-section { margin: 16px 0; }
205
+ .insp-section h3 { font-size: .78rem; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); margin: 0 0 8px; }
206
+ .inspector .fields { grid-template-columns: minmax(90px, 120px) minmax(0, 1fr); margin-bottom: 10px; font-size: .88rem; }
207
+ .inspector pre { max-height: 360px; font-size: .78rem; }
208
+ .inspector p { margin: 6px 0; font-size: .86rem; }
209
+ .attempt, .review { border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; margin: 8px 0; }
210
+ .attempt-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-bottom: 4px; }
211
+ .exec-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 3px 0; font-size: .86rem; }
212
+ .warn { color: var(--warning-text); font-weight: 600; }
213
+ .findings { list-style: none; padding: 0; margin: 6px 0; display: grid; gap: 8px; }
214
+ .finding { border-left: 3px solid var(--line); padding: 2px 0 2px 9px; }
215
+ .finding.plausible { opacity: .82; }
216
+ .finding-head { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
217
+ .finding p { margin: 4px 0; overflow-wrap: anywhere; }
218
+ .finding details { border: 0; padding: 2px 0; font-size: .82rem; }
219
+ .crit a { font-family: var(--mono); }
220
+ ul.plain { list-style: none; padding: 0; margin: 4px 0; display: grid; gap: 4px; font-size: .86rem; }
221
+ ul.plain li.current { font-weight: 650; }
222
+ pre.cmd { max-height: none; }
223
+ .phase-bar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; margin: 6px 0; background: var(--subtle); }
224
+ .phase { min-width: 2px; }
225
+ .phase-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: .76rem; color: var(--muted); }
226
+ .phase-key { display: inline-flex; align-items: center; gap: 4px; }
227
+ .phase-key i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; }
228
+ .ph-preparation { background: #8a929e; }
229
+ .ph-preflight { background: #b48ead; }
230
+ .ph-model { background: #4e9af1; }
231
+ .ph-snapshot { background: #6cc070; }
232
+ .ph-verification { background: #e0a341; }
233
+ .ph-dispatch { background: #4fc2c0; }
234
+ .ph-finalization { background: #d98f6b; }
235
+
236
+ /* the execution chart and the concurrency strip (gantt.js) */
237
+ .gantt, .strip { display: block; font-family: var(--mono); }
238
+ .gt-lane { fill: var(--subtle); }
239
+ .gt-lane.gt-over { fill: var(--warning-bg); }
240
+ .gt-lane-label { fill: var(--muted); font-size: 11px; }
241
+ .gt-lane-label.gt-over { fill: var(--warning-text); }
242
+ .gt-tick { stroke: var(--line); stroke-width: 1; }
243
+ .gt-tick-label { fill: var(--muted); font-size: 10px; }
244
+ .gt-item { cursor: pointer; }
245
+ .gt-box { fill: var(--st, #888); fill-opacity: .2; stroke: var(--st, #888); stroke-width: 1.2; }
246
+ .gt-item:hover .gt-box, .gt-item:focus .gt-box { fill-opacity: .35; }
247
+ .gt-item:focus { outline: none; }
248
+ .gt-item.gt-sel .gt-box { stroke: var(--accent); stroke-width: 2.5; }
249
+ .gt-item.gt-crit .gt-box { stroke-width: 2.4; }
250
+ .gt-ghost .gt-box { fill-opacity: .04; stroke-dasharray: 4 3; }
251
+ .gt-future { opacity: .3; }
252
+ .gt-seg { fill: var(--st, #888); }
253
+ .gt-seg.gt-dwarf { fill-opacity: .55; }
254
+ .gt-label { fill: var(--text); font-size: 10.5px; pointer-events: none; }
255
+ .gt-now { stroke: var(--accent); stroke-width: 2; }
256
+ .cc-area.cc-tasks { fill: var(--accent); fill-opacity: .18; stroke: none; }
257
+ .cc-line.cc-models { fill: none; stroke: var(--accent); stroke-width: 1.5; }
258
+ .cc-cap { stroke: #ae2b36; stroke-width: 1; stroke-dasharray: 5 4; }
259
+ .cc-cap-label { fill: #ae2b36; }
260
+ @media (prefers-color-scheme: dark) { .cc-cap { stroke: #ff9da5; } .cc-cap-label { fill: #ff9da5; } }
261
+ @media (max-width: 1100px) {
262
+ .stage-row { grid-template-columns: minmax(0, 1fr); }
263
+ .inspector { max-height: none; }
264
+ }
265
+ @media (min-width: 1600px) {
266
+ main { padding: 28px 36px; }
267
+ .layout { grid-template-columns: 330px minmax(0, 1fr); }
268
+ }
269
+ @media (max-width: 760px) {
270
+ .topbar { flex-wrap: wrap; gap: 8px 16px; padding: 12px 16px; }
271
+ .topbar > .muted { display: none; }
272
+ .refresh-control { font-size: .85rem; }
273
+ .layout { display: block; }
274
+ .sidebar { border-right: 0; border-bottom: 1px solid var(--line); }
275
+ #run-list { max-height: 280px; }
276
+ main { padding: 20px 14px; }
277
+ .fields { grid-template-columns: 100px minmax(0, 1fr); gap: 7px 10px; }
278
+ .run-header > h2 { font-size: 1.25rem; }
279
+ th, td { padding: 8px; }
280
+ }
281
+
282
+ /* the run cloud (cloudui.js over cloud3d.js): the stage fills the window under the top bar */
283
+ .top-link[aria-current=page] { font-weight: 650; text-decoration-thickness: 2px; }
284
+ body.cloud-mode { height: 100vh; height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
285
+ body.cloud-mode .topbar, body.cloud-mode #errors { flex: none; }
286
+ body.cloud-mode .layout { display: block; flex: 1; min-height: 0; }
287
+ body.cloud-mode .sidebar { display: none; }
288
+ body.cloud-mode main { height: 100%; padding: 0; }
289
+ .cloud-view { position: relative; height: 100%; margin: 0; overflow: hidden; background: var(--bg); }
290
+ .cloud-view:fullscreen { width: 100vw; height: 100vh; }
291
+ .cloud-view .stage-note { display: none; }
292
+ .stage-slot.cloud { position: absolute; inset: 0; }
293
+ .stage-slot.cloud.stage-on, .stage-slot.cloud.stage-loading { height: auto; border: 0; border-radius: 0; }
294
+ .cloud-view:not(.cloud-3d) .stage-slot.cloud { display: none; }
295
+ .stage-canvas.grabbing { cursor: grabbing; }
296
+ .cloud-ui { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
297
+ .cloud-ui > * { pointer-events: auto; }
298
+ .cloud-ui [hidden] { display: none !important; }
299
+ .cloud-bar { position: absolute; left: 12px; right: 12px; top: 12px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px; pointer-events: none; }
300
+ .cloud-bar > * { pointer-events: auto; }
301
+ .cloud-bar-left { display: flex; align-items: baseline; gap: 12px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 9px; background: color-mix(in srgb, var(--surface) 88%, transparent); backdrop-filter: blur(6px); }
302
+ .cloud-bar-left h1 { font-size: 1rem; }
303
+ .cloud-count { color: var(--muted); font-size: .85rem; font-variant-numeric: tabular-nums; }
304
+ .cloud-bar-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
305
+ .cloud-bar-tools > button, .cloud-bar-tools > .seg, .cloud-menu > summary { background: color-mix(in srgb, var(--surface) 92%, transparent); }
306
+ .cloud-bar-tools .seg { align-self: auto; }
307
+ .cloud-filters-btn[aria-expanded=true] { border-color: var(--accent); color: var(--accent); }
308
+ .cloud-menu { position: relative; border: 0; padding: 0; }
309
+ .cloud-menu > summary { list-style: none; padding: 5px 10px; border: 1px solid var(--line); border-radius: 5px; font-weight: 400; }
310
+ .cloud-menu > summary::-webkit-details-marker { display: none; }
311
+ .cloud-menu > summary::after { content: ' ▾'; color: var(--muted); }
312
+ .cloud-menu-body { position: absolute; right: 0; top: calc(100% + 6px); width: 270px; display: grid; gap: 6px; padding: 10px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface); box-shadow: 0 8px 28px rgba(0, 0, 0, .25); }
313
+ .cloud-menu-body p { font-size: .8rem; }
314
+ .cloud-panel { position: absolute; left: 12px; top: 64px; bottom: 12px; width: 300px; overflow: auto; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(6px); }
315
+ .cloud-panel-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 8px; }
316
+ .cloud-panel-head h2 { margin: 0; font-size: .95rem; }
317
+ .cloud-panel input[type=search], .cloud-panel input[type=number] { width: 100%; padding: 6px 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--bg); color: var(--text); font: inherit; }
318
+ .cloud-field { border: 0; border-top: 1px solid var(--line); margin: 10px 0 0; padding: 8px 0 0; min-width: 0; }
319
+ .cloud-field legend { padding: 0; font-size: .72rem; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }
320
+ .cloud-field .cloud-field { border-top: 0; margin-top: 4px; padding-top: 0; }
321
+ .cloud-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
322
+ .cloud-chip { padding: 2px 8px; border-radius: 12px; font-size: .8rem; border-color: var(--line); }
323
+ .cloud-chip[class*=' st-'] { border-left: 3px solid var(--st); }
324
+ .cloud-chip[aria-pressed=true] { background: var(--selected); border-color: var(--accent); color: var(--accent); font-weight: 650; }
325
+ .cloud-check-tools { display: flex; gap: 8px; align-items: center; margin: 4px 0; }
326
+ .cloud-check-tools input { flex: 1; }
327
+ .cloud-checks { list-style: none; margin: 0; padding: 0; max-height: 200px; overflow: auto; }
328
+ .cloud-checks li { display: flex; align-items: center; gap: 6px; padding: 1px 0; }
329
+ .cloud-checks label { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: .86rem; }
330
+ .cloud-check-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
331
+ .cloud-only { visibility: hidden; font-size: .76rem; }
332
+ .cloud-checks li:hover .cloud-only, .cloud-only:focus-visible { visibility: visible; }
333
+ .linkish { border: 0; background: none; padding: 0 2px; color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
334
+ .cloud-select { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: .82rem; color: var(--muted); }
335
+ .cloud-select select { flex: 1; min-width: 0; }
336
+ .cloud-range { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 4px; }
337
+ .cloud-range label { display: grid; gap: 2px; font-size: .78rem; color: var(--muted); }
338
+ .cloud-legend { position: absolute; left: 324px; bottom: 12px; max-width: min(560px, calc(100% - 700px)); padding: 8px 12px; border: 1px solid var(--line); border-radius: 9px; background: color-mix(in srgb, var(--surface) 88%, transparent); backdrop-filter: blur(6px); font-size: .78rem; }
339
+ .cloud-panel[hidden] ~ .cloud-legend { left: 12px; max-width: min(560px, calc(100% - 400px)); }
340
+ .cloud-legend-states { display: flex; flex-wrap: wrap; gap: 4px 12px; list-style: none; margin: 0 0 4px; padding: 0; }
341
+ .cloud-legend-states li { display: inline-flex; align-items: center; gap: 5px; }
342
+ .cloud-legend-how { color: var(--muted); }
343
+ .cloud-card { position: absolute; right: 12px; top: 64px; width: 340px; max-height: calc(100% - 76px); overflow: auto; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); box-shadow: 0 8px 28px rgba(0, 0, 0, .22); }
344
+ .cloud-card-head { display: flex; align-items: center; gap: 8px; font-size: .8rem; }
345
+ .cloud-card-close { margin-left: auto; padding: 0 8px; font-size: 1.1rem; line-height: 1.4; }
346
+ .cloud-card h2 { margin: 8px 0 2px; font-size: 1.05rem; }
347
+ .cloud-card .leds { margin: 8px 0; }
348
+ .cloud-card .fields { grid-template-columns: 96px minmax(0, 1fr); font-size: .85rem; margin-bottom: 8px; }
349
+ .cloud-card-actions { display: flex; flex-wrap: wrap; gap: 6px; }
350
+ a.button { display: inline-block; padding: 5px 10px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); color: var(--text); text-decoration: none; }
351
+ a.button:hover, button.primary:hover { border-color: var(--accent); }
352
+ .primary, a.button.primary { background: var(--accent); border-color: var(--accent); color: var(--surface); font-weight: 650; }
353
+ .cloud-toast { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); display: flex; gap: 12px; align-items: center; padding: 8px 14px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface); box-shadow: 0 8px 28px rgba(0, 0, 0, .25); font-size: .86rem; max-width: calc(100% - 24px); }
354
+ .cloud-list { position: absolute; inset: 64px 12px 12px 324px; overflow: auto; padding: 0 4px 24px; }
355
+ .cloud-view:has(.cloud-panel[hidden]) .cloud-list { left: 12px; }
356
+ .cloud-list-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin: 4px 0 8px; }
357
+ .cloud-view:not(.cloud-3d) .cloud-legend { display: none; }
358
+ @media (max-width: 900px) {
359
+ .cloud-panel { width: auto; right: 12px; bottom: auto; max-height: 55%; top: 108px; }
360
+ .cloud-card { left: 12px; width: auto; top: auto; bottom: 12px; max-height: 45%; }
361
+ .cloud-legend { display: none; }
362
+ .cloud-list { inset: 108px 12px 12px 12px; }
363
+ }
364
+
365
+ /* quick jump (search.js) and notifications (notify.js) */
366
+ .topbar .refresh-control { margin-left: 0; }
367
+ .top-search { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; min-width: 190px; justify-content: space-between; color: var(--muted); }
368
+ kbd { font-family: var(--mono); font-size: .72rem; padding: 0 5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; color: var(--muted); background: var(--bg); }
369
+ .bell { position: relative; display: inline-grid; place-items: center; width: 34px; height: 32px; padding: 0; }
370
+ .bell svg { width: 18px; height: 18px; fill: var(--muted); }
371
+ .bell[aria-expanded=true] svg, .bell:hover svg { fill: var(--accent); }
372
+ .bell-count { position: absolute; top: -6px; right: -7px; min-width: 18px; padding: 0 4px; border-radius: 9px; background: #d23b45; color: #fff; font-size: .68rem; font-weight: 700; line-height: 18px; }
373
+ .notify-pop { position: fixed; z-index: 30; width: min(380px, calc(100vw - 16px)); max-height: min(70vh, 640px); overflow: auto; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); box-shadow: 0 12px 36px rgba(0, 0, 0, .3); }
374
+ .notify-head { display: flex; align-items: baseline; justify-content: space-between; }
375
+ .notify-head h2 { margin: 0 0 6px; font-size: 1rem; }
376
+ .notify-kinds { border: 0; border-top: 1px solid var(--line); margin: 6px 0; padding: 8px 0 0; display: grid; gap: 3px; }
377
+ .notify-kinds legend { padding: 0; font-size: .72rem; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }
378
+ .notify-kinds label { font-size: .88rem; cursor: pointer; }
379
+ .notify-browser { border-top: 1px solid var(--line); padding: 8px 0; display: grid; gap: 6px; justify-items: start; }
380
+ .notify-browser p { font-size: .8rem; }
381
+ .notify-log { list-style: none; margin: 0; padding: 8px 0 0; border-top: 1px solid var(--line); display: grid; gap: 8px; }
382
+ .notify-item { display: grid; gap: 1px; padding-left: 9px; border-left: 3px solid var(--line); font-size: .86rem; }
383
+ .notify-item.unread { border-left-color: var(--accent); }
384
+ .notify-item.bad { border-left-color: #d23b45; }
385
+ .notify-item a { font-weight: 600; }
386
+ .notify-body { overflow-wrap: anywhere; }
387
+ .notify-when { font-size: .74rem; }
388
+ .notify-toast { position: fixed; z-index: 30; right: 16px; bottom: 16px; display: grid; gap: 2px; max-width: min(380px, calc(100vw - 32px)); padding: 10px 14px; border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: 9px; background: var(--surface); box-shadow: 0 10px 30px rgba(0, 0, 0, .28); font-size: .86rem; }
389
+ .notify-toast.bad { border-left-color: #d23b45; }
390
+ .notify-toast a { font-weight: 650; }
391
+ .notify-toast[hidden], .notify-pop[hidden] { display: none; }
392
+ dialog.jump { width: min(680px, calc(100vw - 24px)); max-height: min(72vh, 720px); margin: 12vh auto auto; padding: 0; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); color: var(--text); box-shadow: 0 24px 70px rgba(0, 0, 0, .4); overflow: hidden; }
393
+ dialog.jump[open] { display: flex; flex-direction: column; }
394
+ dialog.jump::backdrop { background: rgba(10, 12, 16, .45); }
395
+ .jump-input { width: 100%; padding: 14px 16px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--text); font: inherit; font-size: 1.02rem; outline: none; }
396
+ .jump-list { list-style: none; margin: 0; padding: 6px; overflow: auto; flex: 1; min-height: 0; }
397
+ .jump-group { padding: 8px 10px 4px; font-size: .7rem; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); }
398
+ .jump-item { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 7px; cursor: pointer; }
399
+ .jump-item[aria-selected=true] { background: var(--selected); }
400
+ .jump-item .led { flex: none; }
401
+ .jump-text { display: grid; min-width: 0; }
402
+ .jump-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
403
+ .jump-label mark { background: none; color: var(--accent); font-weight: 700; }
404
+ .jump-sub { color: var(--muted); font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
405
+ .jump-empty { padding: 14px 10px; color: var(--muted); }
406
+ .jump-foot { margin: 0; padding: 7px 14px; border-top: 1px solid var(--line); color: var(--muted); font-size: .76rem; }
407
+ @media (max-width: 760px) {
408
+ .top-search { min-width: 0; margin-left: 0; }
409
+ .top-search kbd { display: none; }
410
+ }
411
+
412
+ /* the diff viewer (diffview.js): in the run view, in place of the toolbar and the stage */
413
+ .run-view.diff-open > .run-toolbar, .run-view.diff-open > .stage-row, .run-view.diff-open > .strip-wrap { display: none; }
414
+ .diff-view { --add: #e6f4ea; --add-ink: #1d6b35; --del: #fbe9eb; --del-ink: #9f2832; --hunk: #eef1f5; outline: none; }
415
+ @media (prefers-color-scheme: dark) { .diff-view { --add: #17301f; --add-ink: #8fd6a2; --del: #3a1c20; --del-ink: #ff9da5; --hunk: #222a35; } }
416
+ .diff-view[hidden] { display: none; }
417
+ .diff-top { display: flex; align-items: baseline; gap: 12px; }
418
+ .diff-top h2 { margin: 0; }
419
+ .diff-close { margin-left: auto; font-size: .85rem; }
420
+ .diff-sources { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 6px; }
421
+ .diff-source { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border: 1px solid var(--line); border-radius: 14px; color: var(--text); text-decoration: none; font-size: .84rem; background: var(--surface); }
422
+ .diff-source[aria-current=true] { border-color: var(--accent); background: var(--selected); color: var(--accent); font-weight: 650; }
423
+ .diff-meta { margin: 4px 0 10px; font-size: .84rem; }
424
+ .diff-note { padding: 12px 0; }
425
+ .diff-body { display: grid; grid-template-columns: minmax(200px, 280px) minmax(0, 1fr); gap: 16px; align-items: start; }
426
+ .diff-files { position: sticky; top: 10px; max-height: calc(100vh - 20px); overflow: auto; border: 1px solid var(--line); border-radius: 9px; background: var(--surface); padding: 6px; }
427
+ .diff-files ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
428
+ .diff-file-link { display: flex; align-items: center; gap: 6px; padding: 5px 8px; border-radius: 6px; color: var(--text); text-decoration: none; font-family: var(--mono); font-size: .78rem; min-width: 0; }
429
+ .diff-file-link:hover, .diff-file-link[aria-current=true] { background: var(--selected); }
430
+ .diff-dir { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; min-width: 0; }
431
+ .diff-body.no-files { grid-template-columns: minmax(0, 1fr); }
432
+ .diff-base { white-space: nowrap; flex: none; max-width: 60%; overflow: hidden; text-overflow: ellipsis; }
433
+ .diff-stat { margin-left: auto; white-space: nowrap; font-family: var(--mono); font-size: .76rem; color: var(--muted); }
434
+ .diff-add { color: var(--add-ink); } .diff-del { color: var(--del-ink); }
435
+ .diff-loose-link { margin-top: 6px; border-top: 1px solid var(--line); border-radius: 0; font-family: inherit; color: var(--warning-text); }
436
+ .diff-main { min-width: 0; display: grid; gap: 14px; }
437
+ .diff-file { border: 1px solid var(--line); border-radius: 9px; background: var(--surface); overflow: hidden; scroll-margin-top: 12px; }
438
+ .diff-file-head { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: var(--subtle); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
439
+ .diff-path { color: var(--text); text-decoration: none; font-weight: 600; overflow-wrap: anywhere; }
440
+ .diff-path:hover { text-decoration: underline; }
441
+ .diff-file-findings { padding: 6px 10px; display: grid; gap: 6px; border-bottom: 1px solid var(--line); }
442
+ .diff-scroll { overflow-x: auto; }
443
+ .diff-table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: .78rem; line-height: 1.45; }
444
+ .diff-table td { padding: 0 8px; border: 0; vertical-align: top; max-width: none; min-width: 0; font-size: inherit; }
445
+ .diff-table tr:hover { background: none; }
446
+ .diff-table td.ln { width: 1%; min-width: 3.2em; text-align: right; color: var(--muted); user-select: none; border-right: 1px solid var(--line); }
447
+ .diff-table td.mk { width: 1%; padding: 0 2px 0 8px; user-select: none; color: var(--muted); }
448
+ .diff-table td.code { white-space: pre; overflow-wrap: normal; }
449
+ .diff-line.add { background: var(--add); } .diff-line.add td.mk, .diff-line.add td.code { color: var(--add-ink); }
450
+ .diff-line.del { background: var(--del); } .diff-line.del td.mk, .diff-line.del td.code { color: var(--del-ink); }
451
+ .diff-line.meta td.code { color: var(--muted); font-style: italic; }
452
+ .diff-hunk td { background: var(--hunk); color: var(--muted); padding: 3px 10px; white-space: pre; }
453
+ .diff-pin > td { padding: 6px 10px 6px 7.4em; background: var(--surface); font-family: system-ui, sans-serif; font-size: .84rem; white-space: normal; }
454
+ .diff-finding { border: 1px solid var(--line); border-left: 4px solid var(--st, var(--line)); border-radius: 7px; padding: 6px 10px; background: var(--bg); max-width: 900px; scroll-margin: 80px; }
455
+ .diff-finding.sev-P0 { --st: #ae2b36; } .diff-finding.sev-P1 { --st: #a2336f; } .diff-finding.sev-P2 { --st: #985008; } .diff-finding.sev-P3 { --st: #725389; }
456
+ .diff-finding.flash { box-shadow: 0 0 0 3px var(--accent); }
457
+ .diff-finding-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: .78rem; }
458
+ .diff-finding p { margin: 4px 0 0; overflow-wrap: anywhere; }
459
+ .diff-finding details { border: 0; padding: 2px 0 0; font-size: .8rem; }
460
+ .diff-more { margin: 10px; }
461
+ .diff-loose { border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px; display: grid; gap: 8px; background: var(--surface); }
462
+ .diff-loose h3 { margin: 0; font-size: .78rem; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }
463
+ .diff-link { display: inline-block; margin-top: 6px; font-size: .86rem; }
464
+ .diff-link.small { margin: 0 0 0 auto; font-size: .78rem; }
465
+ @media (max-width: 900px) { .diff-body { grid-template-columns: minmax(0, 1fr); } .diff-files { position: static; max-height: 240px; } .diff-pin > td { padding-left: 10px; } }
466
+
467
+ /* Fractal child tasks in the inspector (panel.js) */
468
+ .fractal-tree { list-style: none; margin: 8px 0; padding: 0; display: grid; gap: 3px; }
469
+ .ft-node { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: .86rem; padding-left: 0; }
470
+ .ft-node > a { font-family: var(--mono); font-weight: 600; }
471
+ .ft-node.reserved > a { font-weight: 400; color: var(--muted); }
472
+ .ft-node .muted { font-size: .78rem; }
473
+ .ft-d1 { padding-left: 16px; } .ft-d2 { padding-left: 32px; } .ft-d3 { padding-left: 48px; } .ft-d4 { padding-left: 64px; } .ft-d5 { padding-left: 80px; } .ft-d6 { padding-left: 96px; }
474
+ .ft-node:not(.ft-d0) { border-left: 1px solid var(--line); margin-left: 4px; }
475
+
476
+ /* the model leaderboard (leaderboard.js, modelstats.js) */
477
+ /* the model leaderboard (leaderboard.js): tables of implementers and reviewers, Wilson bars in SVG */
478
+ .lb { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; min-width: 0; }
479
+ .lb-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; }
480
+ .lb-summary { font-size: .88rem; }
481
+ .lb-caveat { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; padding: 10px 14px; border: 1px solid var(--line); border-left: 4px solid var(--warning-text); border-radius: 6px; background: var(--warning-bg); color: var(--text); }
482
+ .lb-caveat p { flex: 1 1 420px; font-size: .88rem; max-width: 92ch; }
483
+ .lb-caveat strong { color: var(--warning-text); }
484
+ .lb-caveat .lb-explore { padding-bottom: 0; font-weight: 600; white-space: nowrap; }
485
+ .lb-filters { margin-bottom: 0; }
486
+ .lb-count { align-self: center; font-size: .82rem; }
487
+ .lb-notes { margin: 0; padding-left: 18px; color: var(--muted); font-size: .82rem; display: grid; gap: 2px; }
488
+ .lb-section h2 { margin-bottom: 4px; }
489
+ .lb-lead { color: var(--muted); font-size: .84rem; max-width: 96ch; margin-bottom: 10px; }
490
+ .lb-table th { white-space: normal; vertical-align: bottom; min-width: 0; line-height: 1.25; }
491
+ .lb-table td { min-width: 0; vertical-align: middle; white-space: nowrap; }
492
+ .lb-table td:nth-child(2) { min-width: 0; }
493
+ .lb-table .lb-num { text-align: right; }
494
+ .lb-zero { color: var(--muted); }
495
+ .lb-sub { display: block; font-size: .72rem; color: var(--muted); }
496
+ .lb-model { font-weight: 600; }
497
+ .lb-few { margin-left: 6px; padding: 0 4px; border: 1px solid var(--line); border-radius: 4px; font-size: .68rem; font-weight: 500; color: var(--muted); vertical-align: 1px; }
498
+ .lb-small td, .lb-small td a, .lb-small strong { color: var(--muted); }
499
+ .lb-rate-box { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
500
+ .lb-rate-text { display: inline-flex; align-items: baseline; justify-content: flex-end; gap: 6px; min-width: 6.5em; }
501
+ .lb-ci, .lb-vbar { display: block; flex: none; overflow: visible; }
502
+ .lb-ci-track { fill: var(--subtle); stroke: var(--line); stroke-width: 1; }
503
+ .lb-ci-grid { fill: var(--line); }
504
+ .lb-ci-band { fill: var(--accent); fill-opacity: .32; }
505
+ .lb-ci-tick { fill: var(--accent); }
506
+ .lb-small .lb-ci-band { fill: var(--muted); fill-opacity: .25; }
507
+ .lb-small .lb-ci-tick { fill: var(--muted); }
508
+ .lb-verdict-box { display: flex; align-items: center; gap: 8px; }
509
+ .lb-verdict-text { font-size: .8rem; }
510
+ .lb-vbar-track { fill: var(--subtle); }
511
+ .lb-vbar-seg { fill: var(--st, var(--muted)); }
512
+ .lb-p0 { color: var(--st, var(--text)); font-weight: 650; }
513
+ .lb-diff summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; list-style: none; }
514
+ .lb-diff summary::before { content: '▸'; color: var(--muted); width: 1em; }
515
+ .lb-diff[open] summary::before { content: '▾'; }
516
+ .lb-diff summary::-webkit-details-marker { display: none; }
517
+ .lb-diff-name { font-weight: 650; }
518
+ .lb-diff summary .muted { font-size: .85rem; font-weight: 400; }
519
+ .lb-diff .table-scroll { margin-top: 10px; }
520
+ .lb-empty { border: 1px dashed var(--line); border-radius: 6px; background: var(--surface); }
521
+ .lb-empty-title { font-weight: 650; color: var(--text); }
522
+ .lb-empty button { margin-top: 12px; }
523
+ @media (max-width: 760px) {
524
+ .lb-caveat .lb-explore { white-space: normal; }
525
+ }
526
+
527
+ /* exports (forge_ui/export.py): the dialog that makes one, and the page it makes */
528
+ .export-btn { margin-left: auto; font-size: .85rem; }
529
+ dialog.export-dialog { width: min(560px, calc(100vw - 24px)); padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); color: var(--text); box-shadow: 0 24px 70px rgba(0, 0, 0, .4); }
530
+ dialog.export-dialog::backdrop { background: rgba(10, 12, 16, .45); }
531
+ dialog.export-dialog h2 { margin-bottom: 8px; }
532
+ .export-opt { display: flex; gap: 10px; align-items: flex-start; margin: 12px 0; cursor: pointer; }
533
+ .export-opt input { margin-top: 4px; }
534
+ .export-opt span { display: grid; gap: 2px; }
535
+ .export-opt .muted { font-size: .84rem; }
536
+ .export-note:empty { display: none; }
537
+ .export-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
538
+ .snapshot-banner { padding: 7px 22px; background: var(--selected); border-bottom: 1px solid var(--line); font-size: .85rem; overflow-wrap: anywhere; }
539
+ body.snapshot .top-link, body.snapshot #bell, body.snapshot .refresh-control, body.snapshot .topbar > .muted { display: none; }
540
+
541
+ /* Files: the run view's third mode (files.js), in the stage's place */
542
+ .run-view.files-open .stage-slot, .run-view.files-open .stage-note, .run-view.files-open #graph2d, .run-view.files-open .strip-wrap, .run-view.files-open .replay, .run-view.files-open .overlays { display: none; }
543
+ .files-view[hidden] { display: none; }
544
+ .files-view { min-width: 0; }
545
+
546
+ /* the files heatmap (files.js) */
547
+ /* the files heatmap (files.js): files × tasks, coloured by class (the page CSP refuses style attributes) */
548
+ .fm { --fm-heat: var(--accent); --fm-plan: var(--muted); --fm-drift: #a85d00; --fm-bad: #c42b3a; --fm-overlap: #7b4fa0; }
549
+ @media (prefers-color-scheme: dark) { .fm { --fm-drift: #f3bb77; --fm-bad: #ff8a95; --fm-overlap: #d2b0ee; } }
550
+ .fm-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
551
+ .fm-bar { align-items: center; margin-bottom: 8px; }
552
+ .fm-bar .filter:not(.check) { flex-direction: row; align-items: center; gap: 6px; font-size: .85rem; }
553
+ .fm-filter { width: min(280px, 60vw); }
554
+ .fm-toggles { display: flex; flex-wrap: wrap; gap: 2px 12px; }
555
+ .fm-toggles .filter.check { padding-bottom: 0; gap: 5px; cursor: pointer; }
556
+ .fm-tools { display: flex; gap: 6px; }
557
+ .fm-tools button { font-size: .82rem; padding: 3px 9px; }
558
+ .fm-swatch, .fm-ramp { display: inline-block; flex: none; vertical-align: middle; }
559
+ .fm-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; margin: 0 0 4px; font-size: .78rem; color: var(--muted); }
560
+ .fm-key { display: inline-flex; align-items: center; gap: 5px; }
561
+ .fm-count { margin: 0 0 8px; font-size: .85rem; color: var(--muted); font-variant-numeric: tabular-nums; }
562
+ .fm-note { margin: 6px 0; font-size: .85rem; }
563
+ .fm-empty { color: var(--muted); padding: 12px 0; }
564
+ .fm-scroll { overflow: auto; width: fit-content; max-width: 100%; max-height: min(72vh, 960px); border: 1px solid var(--line); border-radius: 8px; background: var(--surface); overscroll-behavior: contain; }
565
+ .fm-sheet { width: max-content; }
566
+ .fm-headrow { display: flex; position: sticky; top: 0; z-index: 2; background: var(--surface); border-bottom: 1px solid var(--line); }
567
+ .fm-bodyrow { display: flex; }
568
+ .fm-corner, .fm-labels { position: sticky; left: 0; background: var(--surface); border-right: 1px solid var(--line); }
569
+ .fm-corner { z-index: 3; }
570
+ .fm-labels { z-index: 1; }
571
+ .fm svg { font-family: var(--mono); }
572
+ .fm-scroll svg { display: block; flex: none; }
573
+ .fm-axis { fill: var(--muted); font-size: 10.5px; letter-spacing: .04em; }
574
+ .fm-wave text { fill: var(--muted); font-size: 10px; }
575
+ .fm-wave line { stroke: var(--muted); stroke-width: 1; }
576
+ .fm-waveband { fill: var(--subtle); fill-opacity: .7; }
577
+ .fm-wavesep { stroke: var(--line); stroke-width: 1; }
578
+ .fm-colhead { cursor: pointer; }
579
+ .fm-colhead text { fill: var(--text); font-size: 11px; }
580
+ .fm-colhead:hover text { fill: var(--accent); }
581
+ .fm-colhead.fm-sel text { fill: var(--accent); font-weight: 700; }
582
+ .fm-st { fill: var(--st, #888); }
583
+ .fm-colsel { fill: var(--selected); pointer-events: none; }
584
+ .fm-hover { fill: var(--accent); fill-opacity: .08; pointer-events: none; }
585
+ .fm-zebra { fill: var(--subtle); fill-opacity: .55; }
586
+ .fm-dirband { fill: var(--subtle); }
587
+ .fm-hit { fill: transparent; }
588
+ .fm-label { fill: var(--text); font-size: 12px; }
589
+ .fm-dirrow { cursor: pointer; }
590
+ .fm-dirrow .fm-label { font-weight: 650; }
591
+ .fm-dirrow:hover .fm-label { fill: var(--accent); }
592
+ .fm-tri { fill: var(--muted); }
593
+ .fm-num { fill: var(--muted); font-size: 10.5px; }
594
+ .fm-cell { cursor: pointer; }
595
+ .fm-touch { fill: var(--fm-heat); }
596
+ .fm-plan { fill: transparent; stroke: var(--fm-plan); stroke-width: 1.3; }
597
+ .fm-exist { fill: transparent; stroke: var(--fm-plan); stroke-width: 1.3; stroke-dasharray: 2.5 2; }
598
+ .fm-conflict { fill: none; stroke: var(--fm-bad); stroke-width: 2.2; }
599
+ .fm-hatch-bg { fill: var(--fm-drift); fill-opacity: .14; }
600
+ .fm-hatch-line { stroke: var(--fm-drift); stroke-width: 1.5; }
601
+ .fm-overlap { fill: var(--fm-overlap); stroke: var(--surface); stroke-width: 1; }
602
+ .fm-colhead:focus, .fm-dirrow:focus, .fm-cell:focus, .fm-pop:focus { outline: none; }
603
+ .fm-colhead:focus-visible .fm-hit { stroke: var(--accent); stroke-width: 2; }
604
+ .fm-ring { fill: none; stroke: var(--accent); stroke-width: 2; pointer-events: none; }
605
+ .fm-dirrow:focus-visible .fm-hit { fill: var(--selected); }
606
+ .fm-dirrow:focus-visible .fm-label { fill: var(--accent); text-decoration: underline; }
607
+ .fm-pop rect { fill: var(--surface); stroke: var(--accent); stroke-width: 1.2; }
608
+ .fm-pop text { fill: var(--accent); font-size: 11.5px; text-decoration: underline; }
609
+ .fm-pop:hover rect, .fm-pop:focus-visible rect { fill: var(--selected); stroke-width: 2; }
610
+ .fm-lists { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 14px 28px; margin-top: 16px; }
611
+ .fm-list h3 { margin: 0 0 6px; font-size: .78rem; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); cursor: help; }
612
+ .fm-list ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: .85rem; }
613
+ .fm-list li { overflow-wrap: anywhere; }
614
+ .fm-list p { font-size: .85rem; }
615
+ .fm-task { font: inherit; font-family: var(--mono); font-size: .82rem; }
616
+ .fm-more { border: 0; padding: 4px 0 0; }
617
+ .fm-more > summary { font-weight: 400; font-size: .85rem; color: var(--muted); }
618
+ .fm-more > ul { margin-top: 4px; }