@wendellresearch-ai/benchwarmers 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +152 -147
- package/BENCHMARKS.md +262 -262
- package/GATEWAY.md +415 -272
- package/NOTICE +28 -28
- package/PRIVACY.md +46 -46
- package/README.md +408 -314
- package/SECURITY.md +83 -83
- package/TERMS.md +22 -22
- package/USAGE.md +186 -163
- package/VERSION +1 -1
- package/bin/benchwarmers.js +16 -74
- package/cli.py +674 -0
- package/examples/config/gateway.json +5 -5
- package/examples/config/model-roles.json +11 -11
- package/gateway.py +939 -755
- package/launcher.py +120 -0
- package/mcp_server.py +266 -266
- package/metrics/alerts.py +116 -116
- package/metrics/aliases.py +41 -41
- package/metrics/bench_collections.py +141 -141
- package/metrics/catalog.py +304 -295
- package/metrics/client.py +804 -394
- package/metrics/cliproxy.py +191 -191
- package/metrics/connect.py +691 -691
- package/metrics/cost.py +171 -152
- package/metrics/decide.py +227 -227
- package/metrics/discover.py +318 -318
- package/metrics/endpoints.py +436 -436
- package/metrics/formats.py +1021 -0
- package/metrics/guard.py +647 -592
- package/metrics/learn.py +234 -221
- package/metrics/ledger.py +148 -0
- package/metrics/litellm_hub.py +206 -206
- package/metrics/model_roles.py +94 -84
- package/metrics/offload.py +166 -166
- package/metrics/owui.py +205 -205
- package/metrics/pacing.py +248 -0
- package/metrics/paths.py +60 -60
- package/metrics/quota.py +383 -0
- package/metrics/route.py +581 -579
- package/metrics/scheduler.py +275 -275
- package/metrics/sources.py +167 -167
- package/metrics/wrong.py +144 -144
- package/package.json +69 -65
- package/perf/README.md +89 -89
- package/perf/run.py +284 -261
- package/scripts/auto_retire.py +367 -367
- package/scripts/check.py +113 -106
- package/scripts/check_deprecations.py +378 -378
- package/scripts/check_themes.py +103 -103
- package/scripts/init.py +124 -124
- package/scripts/list_served.py +78 -78
- package/scripts/notice.py +78 -78
- package/scripts/onboard.py +410 -331
- package/scripts/provider_tags.py +129 -129
- package/scripts/reprefix.py +136 -136
- package/scripts/sync_config.py +105 -105
- package/scripts/test_auth.py +255 -255
- package/scripts/test_cli.py +189 -0
- package/scripts/test_client.py +277 -233
- package/scripts/test_connect.py +222 -222
- package/scripts/test_first_run.py +180 -180
- package/scripts/test_formats.py +549 -0
- package/scripts/test_hubs.py +328 -328
- package/scripts/test_launcher.py +67 -0
- package/scripts/test_llm_log.py +85 -81
- package/scripts/test_mcp.py +178 -178
- package/scripts/test_merged.py +215 -214
- package/scripts/test_no_owui.py +291 -291
- package/scripts/test_owui.py +90 -90
- package/scripts/test_quota.py +334 -0
- package/scripts/test_serve_edit.py +453 -438
- package/scripts/test_server_json.py +79 -0
- package/scripts/test_verdict.py +102 -98
- package/scripts/test_vision.py +231 -228
- package/serve.py +3972 -3764
- package/suite/mine.py +154 -154
- package/suite/pace.py +145 -145
- package/suite/run.py +1046 -1042
- package/suite/seed.py +421 -421
- package/suite/tasks/claim-alias-unbound/fixtures/onboard.py +286 -286
- package/suite/tasks/claim-error-text-string/fixtures/decide.py +187 -187
- package/suite/tasks/claim-list-body/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-member-nominated-twice/fixtures/gateway.py +284 -284
- package/suite/tasks/claim-nominee-uses-slot/fixtures/gateway.py +284 -284
- package/suite/tasks/claim-silent-exit/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-sse-hang/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-unknown-nominee-crash/fixtures/gateway.py +284 -284
- package/suite/tasks/rebench-matchms-809-bug/task.json +23 -23
- package/suite/tasks/rebench-matchms-809-control/task.json +27 -27
- package/suite/tasks/rebench-more-itertools-1028-bug/task.json +23 -23
- package/suite/tasks/rebench-more-itertools-1028-control/task.json +27 -27
- package/suite/tasks/rebench-narwhals-2864-bug/task.json +23 -23
- package/suite/tasks/rebench-narwhals-2864-control/task.json +27 -27
- package/suite/tasks/rebench-quantecon-py-769-bug/task.json +23 -23
- package/suite/tasks/rebench-quantecon-py-769-control/task.json +27 -27
- package/suite/tasks/rebench-scrapy-6867-bug/task.json +23 -23
- package/suite/tasks/rebench-scrapy-6867-control/task.json +27 -27
- package/ui/bench.css +430 -425
- package/ui/bench.js +1757 -1576
- package/ui/themes/dark.css +35 -35
- package/ui/themes/hardwood.css +52 -52
- package/ui/themes/rainforest.css +32 -32
package/ui/bench.css
CHANGED
|
@@ -1,425 +1,430 @@
|
|
|
1
|
-
/* Benchwarmers. The theme's colour tokens arrive first (ui/themes/*.css, the
|
|
2
|
-
Wendell Research palette by default, emitted by serve.py); the values below
|
|
3
|
-
are derived from them: grounds mixed from a theme colour, and the bench's
|
|
4
|
-
own spacing. A theme sets colours only. */
|
|
5
|
-
|
|
6
|
-
:root {
|
|
7
|
-
--ok: var(--primary);
|
|
8
|
-
--ok-ground: color-mix(in oklab, var(--primary) 13%, var(--paper-2));
|
|
9
|
-
--warn-ground: color-mix(in oklab, var(--signal) 55%, var(--paper-2));
|
|
10
|
-
--err-ground: color-mix(in oklab, var(--err) 11%, var(--paper-2));
|
|
11
|
-
--quiet-ground: var(--band);
|
|
12
|
-
--panel: var(--paper-2);
|
|
13
|
-
--step-1: color-mix(in oklab, var(--band) 55%, var(--paper));
|
|
14
|
-
color-scheme: var(--scheme, light);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
* { box-sizing: border-box; }
|
|
18
|
-
[hidden] { display: none !important; }
|
|
19
|
-
html { -webkit-text-size-adjust: 100%; }
|
|
20
|
-
body {
|
|
21
|
-
margin: 0;
|
|
22
|
-
/* A theme may draw the page's ground (Hardwood's maple court) and a line
|
|
23
|
-
across the top (its crimson court line); the others are plain paper. */
|
|
24
|
-
background: var(--floor, var(--paper));
|
|
25
|
-
border-top: .4rem solid var(--court-line, transparent);
|
|
26
|
-
color: var(--ink);
|
|
27
|
-
font: 400 1rem/1.55 var(--font-display);
|
|
28
|
-
-webkit-font-smoothing: antialiased;
|
|
29
|
-
}
|
|
30
|
-
::selection { background: var(--signal); color: var(--ink); }
|
|
31
|
-
a { color: var(--link); text-underline-offset: .18em; }
|
|
32
|
-
:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; border-radius: 2px; }
|
|
33
|
-
code, .mono, td.num, .chip, .alias {
|
|
34
|
-
font-family: var(--font-mono);
|
|
35
|
-
font-variant-numeric: tabular-nums;
|
|
36
|
-
}
|
|
37
|
-
code { font-size: .875em; background: var(--step-1); padding: .05rem .3rem; border-radius: var(--radius); }
|
|
38
|
-
h1, h2, h3 { line-height: 1.1; letter-spacing: -.02em; text-wrap: balance; }
|
|
39
|
-
|
|
40
|
-
/* ---- header --------------------------------------------------------- */
|
|
41
|
-
/* The page is wider than the theme's reading measure: with a sidebar, a
|
|
42
|
-
76rem page left a narrow column and wide empty margins on a large screen.
|
|
43
|
-
Prose inside panels keeps its own measure (.panel > .sub). */
|
|
44
|
-
/* One line: the name on its bench, the credit beside it, the actions pushed
|
|
45
|
-
to the far end. */
|
|
46
|
-
header {
|
|
47
|
-
max-width: var(--page, 104rem); margin: 0 auto;
|
|
48
|
-
padding: 1.5rem var(--gutter) 1rem;
|
|
49
|
-
display: flex; flex-wrap: wrap; align-items: center; column-gap: 1.25rem;
|
|
50
|
-
}
|
|
51
|
-
header h1 { margin: 0; font-size: 2.25rem; font-weight: 800; letter-spacing: -.04em; line-height: 1; }
|
|
52
|
-
/* The name sits on a team bench: a seat in the team's colour (the theme's
|
|
53
|
-
brand, or --bench-seat) on two legs joined by a rail. Drawn in CSS from the
|
|
54
|
-
font size, so it scales with the heading. With line-height 1 the letters
|
|
55
|
-
end about .14em above the box, so the seat's top is put there: the name
|
|
56
|
-
rests on it. */
|
|
57
|
-
header h1 span { position: relative; display: inline-block; padding: 0 .14em .6em; }
|
|
58
|
-
header h1 span::after { /* the seat */
|
|
59
|
-
content: ""; position: absolute; left: -.08em; right: -.08em; bottom: .46em; height: .28em;
|
|
60
|
-
background: var(--bench-seat, var(--brand)); border-radius: .06em;
|
|
61
|
-
box-shadow: inset 0 .055em 0 rgb(255 255 255 / .28), 0 .05em 0 rgb(0 0 0 / .3);
|
|
62
|
-
}
|
|
63
|
-
header h1 span::before { /* legs and the rail between them */
|
|
64
|
-
--leg: var(--bench-leg, var(--ink-2));
|
|
65
|
-
content: ""; position: absolute; left: .18em; right: .18em; bottom: 0; height: .5em;
|
|
66
|
-
background:
|
|
67
|
-
linear-gradient(var(--leg), var(--leg)) left top / .11em 100% no-repeat,
|
|
68
|
-
linear-gradient(var(--leg), var(--leg)) right top / .11em 100% no-repeat,
|
|
69
|
-
linear-gradient(var(--leg), var(--leg)) center 66% / 100% .07em no-repeat;
|
|
70
|
-
}
|
|
71
|
-
/* The credit at the bench's feet: level with the bottom of the name's group. */
|
|
72
|
-
header .sub { align-self: flex-end; margin: 0 auto 0 -.6rem; line-height: 1; color: var(--muted); font-size: .9375rem; }
|
|
73
|
-
header .sub a { color: var(--ink); font-weight: 500; text-decoration-color: var(--brand); }
|
|
74
|
-
/* Right-aligned, on the name's line or, when it does not fit, on its own. */
|
|
75
|
-
.head-actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center;
|
|
76
|
-
margin-left: auto; justify-content: flex-end; }
|
|
77
|
-
|
|
78
|
-
/* ---- buttons -------------------------------------------------------- */
|
|
79
|
-
button { font: inherit; cursor: pointer; }
|
|
80
|
-
.btn {
|
|
81
|
-
display: inline-flex; align-items: center; gap: .4rem;
|
|
82
|
-
padding: .5rem .9rem; border-radius: var(--radius);
|
|
83
|
-
border: 1px solid var(--ink); background: var(--panel); color: var(--ink);
|
|
84
|
-
font-weight: 500; font-size: .9375rem;
|
|
85
|
-
transition: transform .15s ease, box-shadow .15s ease, background-color .15s ease;
|
|
86
|
-
}
|
|
87
|
-
.btn:hover { background: var(--step-1); }
|
|
88
|
-
.btn.primary { background: var(--ink); color: var(--paper); box-shadow: 4px 4px 0 var(--brand); }
|
|
89
|
-
.btn.primary:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--brand); background: var(--ink); }
|
|
90
|
-
.btn.danger { background: var(--err); border-color: var(--err); color: var(--on-err, #fff); }
|
|
91
|
-
.btn.danger:hover { background: color-mix(in oklab, var(--err) 86%, #000); }
|
|
92
|
-
.btn.small { padding: .25rem .6rem; font-size: .875rem; }
|
|
93
|
-
.btn:disabled { opacity: .5; cursor: default; transform: none; box-shadow: none; }
|
|
94
|
-
.btn.fresh { background: var(--signal); border-color: var(--ink); }
|
|
95
|
-
.btn.fresh:hover { background: var(--signal); transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
|
|
96
|
-
.linkish { background: none; border: 0; padding: 0; color: var(--link); text-decoration: underline;
|
|
97
|
-
text-underline-offset: .18em; font-size: inherit; }
|
|
98
|
-
|
|
99
|
-
/* ---- layout --------------------------------------------------------- */
|
|
100
|
-
main { max-width: var(--page, 104rem); margin: 0 auto; padding: 0 var(--gutter) 4rem; }
|
|
101
|
-
|
|
102
|
-
/* problems: what needs a person, each with the action that resolves it */
|
|
103
|
-
.problems { background: var(--sheet, var(--panel)); border-radius: 14px; padding: 1rem 1.4rem; margin: .5rem 0 1.5rem;
|
|
104
|
-
box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 12px 32px -14px rgb(0 0 0 / .14);
|
|
105
|
-
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
106
|
-
.problems h2 { margin: 0 0 .25rem; font-size: 1.25rem; font-weight: 700; }
|
|
107
|
-
.problems > p { margin: 0 0 .5rem; color: var(--muted); font-size: .9375rem; }
|
|
108
|
-
.problem { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .25rem 1rem;
|
|
109
|
-
align-items: center; padding: .55rem .75rem; margin: 0 -.75rem; border-radius: var(--radius); }
|
|
110
|
-
.problem:hover { background: var(--step-1); }
|
|
111
|
-
.problems details { margin-top: .5rem; }
|
|
112
|
-
.problems details > summary { cursor: pointer; font-weight: 500; padding: .4rem 0; }
|
|
113
|
-
.problems details > summary .muted { font-weight: 400; }
|
|
114
|
-
.problem .what { font-weight: 500; }
|
|
115
|
-
.problem .why { color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
116
|
-
.problem .acts, .endpoint .acts, .ep .acts { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: flex-end; }
|
|
117
|
-
.row-input { display: flex; gap: .5rem; align-items: center; margin-top: .35rem; }
|
|
118
|
-
.row-input input { flex: 1; min-width: 0; margin: 0 !important; }
|
|
119
|
-
.sub-head { font-weight: 600; margin: 1rem 0 .25rem; }
|
|
120
|
-
.problem .chip { margin-right: .4rem; }
|
|
121
|
-
.problems .head { display: flex; align-items: baseline; gap: .5rem; }
|
|
122
|
-
.problems .head h2 { margin-bottom: .25rem; }
|
|
123
|
-
.problems .sep { display: none; color: var(--muted); }
|
|
124
|
-
/* Hidden (bench.js): one line, "Action needed · 3 · show", until something new */
|
|
125
|
-
.problems.collapsed { padding: .5rem 1.25rem; }
|
|
126
|
-
.problems.collapsed > :not(.head) { display: none; }
|
|
127
|
-
.problems.collapsed .head h2 { margin: 0; font-size: 1rem; }
|
|
128
|
-
.problems.collapsed .sep { display: inline; }
|
|
129
|
-
|
|
130
|
-
/* pages: a grouped sidebar (Observe, Gateway, Control); the group names and
|
|
131
|
-
the active page carry the theme's brand colour. A theme with a floor backs
|
|
132
|
-
the sidebar with frosted cream (--rail) so it reads over the court. On a
|
|
133
|
-
narrow screen the groups sit in a row above the page. */
|
|
134
|
-
.layout { display: grid; grid-template-columns: 12rem minmax(0, 1fr); gap: 1.5rem; align-items: start; }
|
|
135
|
-
.tabs { position: sticky; top: 1rem; display: flex; flex-direction: column; gap: 1.1rem;
|
|
136
|
-
background: var(--rail, transparent); padding: var(--rail-pad, 0); border-radius: 14px;
|
|
137
|
-
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
138
|
-
.tabs .group { display: flex; flex-direction: column; align-items: flex-start; gap: .55rem; }
|
|
139
|
-
.tabs h2 { margin: 0 0 .2rem; font-size: .75rem; font-weight: 700; letter-spacing: .08em;
|
|
140
|
-
text-transform: uppercase; color: color-mix(in oklab, var(--brand) 72%, var(--ink)); }
|
|
141
|
-
/* the brand, pulled toward the ink so small text stays legible in any theme */
|
|
142
|
-
/* No bottom padding and a tight line height, so the box ends just under the
|
|
143
|
-
letters; the spacing between pages is the group's gap instead. */
|
|
144
|
-
.tabs button { background: none; border: 0; padding: 0; line-height: 1.15; color: var(--muted); text-align: left;
|
|
145
|
-
font-size: 1rem; font-weight: 500; }
|
|
146
|
-
.tabs button:hover { color: var(--ink); }
|
|
147
|
-
/* The active page: a highlighter stroke across the bottom of its letters,
|
|
148
|
-
the header's old mark. */
|
|
149
|
-
.tabs button[aria-selected="true"] { color: var(--ink); font-weight: 700;
|
|
150
|
-
box-shadow: inset 0 -.42em 0 var(--signal); }
|
|
151
|
-
/* Collections, the bench's own idea: a small brand sparkle after it. It
|
|
152
|
-
hangs outside the button, so the active page's stroke still runs under
|
|
153
|
-
the word alone. */
|
|
154
|
-
.tabs button[data-tab="collections"] { position: relative; }
|
|
155
|
-
.tabs button[data-tab="collections"]::after {
|
|
156
|
-
content: ""; position: absolute; left: calc(100% + .3em); top: -.05em; width: .75em; height: .75em;
|
|
157
|
-
background: var(--brand);
|
|
158
|
-
clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
|
|
159
|
-
.tab { display: none; } .tab.active { display: block; }
|
|
160
|
-
/* One surface for the page's content: its panels are sections of it,
|
|
161
|
-
divided by a hairline, rather than separate boxes with gaps between. A
|
|
162
|
-
theme with a floor makes it frosted (--sheet, --glass). */
|
|
163
|
-
.panes { background: var(--sheet, var(--panel)); border-radius: 14px;
|
|
164
|
-
box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 12px 32px -14px rgb(0 0 0 / .14);
|
|
165
|
-
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
166
|
-
.panes .panel { background: transparent; border-radius: 0; padding: 1.4rem 1.6rem 1.5rem; }
|
|
167
|
-
.panes .tab > .panel + .panel { border-top: 1px solid var(--line); }
|
|
168
|
-
@media (max-width: 52rem) {
|
|
169
|
-
.layout { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
|
|
170
|
-
.tabs { position: static; flex-direction: row; flex-wrap: wrap; gap: .5rem 1.5rem; }
|
|
171
|
-
.tabs .group { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: .1rem 1rem; }
|
|
172
|
-
.tabs h2 { margin: 0; }
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/* settings, connections, logs, info */
|
|
176
|
-
.themes { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .75rem; }
|
|
177
|
-
td.set-by { font-size: .8125rem; color: var(--muted); white-space: nowrap; }
|
|
178
|
-
.theme-card { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: .35rem .5rem;
|
|
179
|
-
padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer; }
|
|
180
|
-
.theme-card:has(input:checked) { border-color: var(--ink); box-shadow: 3px 3px 0 var(--brand); }
|
|
181
|
-
.theme-card .swatch, .theme-card a { grid-column: 2; }
|
|
182
|
-
.swatch { display: flex; gap: 2px; }
|
|
183
|
-
.swatch span { width: 1rem; height: 1rem; border-radius: 2px; border: 1px solid var(--line); }
|
|
184
|
-
.theme-card a { font-size: .8125rem; }
|
|
185
|
-
table.facts th { text-align: left; padding-right: 1.5rem; color: var(--muted); font-weight: 500; }
|
|
186
|
-
details.panel > summary { cursor: pointer; }
|
|
187
|
-
details.panel[open] > summary { margin-bottom: .75rem; }
|
|
188
|
-
.log-line { font-size: .8125rem; padding: .1rem 0; overflow-wrap: anywhere; }
|
|
189
|
-
|
|
190
|
-
.panel { background: var(--panel); border-radius: var(--radius); padding: 1.1rem 1.25rem 1.25rem; }
|
|
191
|
-
.panel > h2 { margin: 0; font-size: 1.375rem; font-weight: 700; }
|
|
192
|
-
/* A section's heading carries a short bar of the brand colour: the accent a
|
|
193
|
-
mostly-white theme needs, and a marker where sections meet on one surface. */
|
|
194
|
-
.panes .panel > h2::before { content: ""; display: inline-block; width: .22em; height: .8em; margin-right: .45em;
|
|
195
|
-
vertical-align: -.05em; border-radius: 2px; background: var(--brand); }
|
|
196
|
-
.panel > .sub { margin: .3rem 0 1rem; color: var(--muted); font-size: .9375rem; max-width: 70ch; }
|
|
197
|
-
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.25rem; margin: 0 0 .75rem; }
|
|
198
|
-
.toolbar input[type=search] { font: inherit; font-size: .9375rem; padding: .4rem .6rem; min-width: 14rem;
|
|
199
|
-
border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); color: var(--ink); }
|
|
200
|
-
.toolbar label { font-size: .9375rem; display: inline-flex; align-items: center; gap: .4rem; cursor: pointer; }
|
|
201
|
-
.toolbar select { font: inherit; font-size: .9375rem; padding: .35rem .4rem; border: 1px solid var(--line);
|
|
202
|
-
border-radius: var(--radius); background: var(--paper); color: var(--ink); }
|
|
203
|
-
tr.pick-row { cursor: pointer; }
|
|
204
|
-
a.dmodel { color: var(--ink); text-decoration: none; font-weight: 500; }
|
|
205
|
-
a.dmodel:hover .alias { box-shadow: inset 0 -.3em 0 var(--signal); }
|
|
206
|
-
/* Connections: each endpoint, its models folded under it */
|
|
207
|
-
.ep { padding: .75rem 0; border-top: 1px solid var(--line); }
|
|
208
|
-
.ep-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .4rem 1rem; align-items: center; }
|
|
209
|
-
.ep .base { color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
210
|
-
.ep details.models > summary { cursor: pointer; color: var(--link); font-size: .9375rem; margin-top: .3rem; }
|
|
211
|
-
.ep details.models[open] > summary { margin-bottom: .5rem; }
|
|
212
|
-
.hint { color: var(--muted); font-size: .875rem; margin: .9rem 0 0; max-width: 75ch; }
|
|
213
|
-
|
|
214
|
-
/* key: folded until asked for */
|
|
215
|
-
details.key { margin: 1rem 0 0; }
|
|
216
|
-
details.key > summary { cursor: pointer; color: var(--link); font-size: .9375rem; width: max-content; }
|
|
217
|
-
details.key dl { margin: .5rem 0 0; display: grid; grid-template-columns: max-content minmax(0, 60ch);
|
|
218
|
-
gap: .35rem 1rem; font-size: .9375rem; }
|
|
219
|
-
details.key dt { font-weight: 700; }
|
|
220
|
-
details.key dd { margin: 0; color: var(--ink); }
|
|
221
|
-
|
|
222
|
-
/* ---- tables --------------------------------------------------------- */
|
|
223
|
-
.scroll { overflow-x: auto; }
|
|
224
|
-
table { border-collapse: collapse; width: 100%; font-size: .9375rem; }
|
|
225
|
-
th, td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
|
|
226
|
-
th { font-size: .875rem; font-weight: 700; color: var(--ink); white-space: nowrap; }
|
|
227
|
-
th[data-sortable] { cursor: pointer; user-select: none; }
|
|
228
|
-
th[data-sortable]::after { content: ""; display: inline-block; width: .9em; color: var(--muted); }
|
|
229
|
-
th[aria-sort=ascending]::after { content: " \2191"; }
|
|
230
|
-
th[aria-sort=descending]::after { content: " \2193"; }
|
|
231
|
-
td.num, th.num { text-align: right; }
|
|
232
|
-
/* the per-connection model cards on Connections: one fixed column plan */
|
|
233
|
-
table.model-cards { table-layout: fixed; min-width: 52rem; }
|
|
234
|
-
.panel:has(> table.model-cards) { overflow-x: auto; } /* scrolls on a narrow window instead of wrapping numbers */
|
|
235
|
-
table.model-cards td.num { white-space: nowrap; }
|
|
236
|
-
table.model-cards col.c-model { width: 24%; }
|
|
237
|
-
table.model-cards col.c-via { width: 13%; }
|
|
238
|
-
table.model-cards col.c-n { width: 10%; }
|
|
239
|
-
table.model-cards col.c-input { width: 19%; }
|
|
240
|
-
table.model-cards col.c-lim { width: 6%; }
|
|
241
|
-
table.model-cards td { overflow-wrap: anywhere; }
|
|
242
|
-
tbody tr:hover > td { background: var(--step-1); }
|
|
243
|
-
tr.retired > td { color: var(--muted); }
|
|
244
|
-
tr.retired .alias { text-decoration: line-through; }
|
|
245
|
-
body:not(.show-retired) tr.retired { display: none; }
|
|
246
|
-
body:not(.show-paid) tr.paid { display: none; }
|
|
247
|
-
.muted { color: var(--muted); }
|
|
248
|
-
.ok { color: var(--ok); } .warn { color: var(--warn); } .err { color: var(--err); }
|
|
249
|
-
|
|
250
|
-
a.model { color: var(--ink); text-decoration: none; font-weight: 500; }
|
|
251
|
-
a.model:hover .alias { box-shadow: inset 0 -.3em 0 var(--signal); }
|
|
252
|
-
.conn { display: block; color: var(--muted); font-size: .8125rem; }
|
|
253
|
-
|
|
254
|
-
/* status chips */
|
|
255
|
-
.chip { display: inline-block; padding: .1rem .5rem; border-radius: 999px; font-size: .8125rem;
|
|
256
|
-
font-weight: 500; white-space: nowrap; background: var(--quiet-ground); color: var(--muted); }
|
|
257
|
-
.chip.ok { background: var(--ok-ground); color: var(--primary-deep); }
|
|
258
|
-
.chip.warn { background: var(--warn-ground); color: var(--ink); }
|
|
259
|
-
.chip.err { background: var(--err-ground); color: var(--err); }
|
|
260
|
-
.chip.new { background: var(--sky); color: var(--ink-deep); }
|
|
261
|
-
/* an endpoint a model is reached through: outlined, so it reads as a place, not a state */
|
|
262
|
-
.chip.via { background: transparent; border: 1px solid var(--line); color: var(--ink); font-family: var(--font-mono); }
|
|
263
|
-
button.chip { font-family: inherit; border: 0; cursor: pointer; }
|
|
264
|
-
button.chip:hover { outline: 1px solid currentColor; }
|
|
265
|
-
|
|
266
|
-
/* helped bar: share of judged offloads that helped */
|
|
267
|
-
.helped { display: inline-flex; align-items: center; gap: .5rem; }
|
|
268
|
-
.meter { width: 4.5rem; height: .5rem; background: var(--band); border-radius: 999px; overflow: hidden; }
|
|
269
|
-
.meter span { display: block; height: 100%; background: var(--brand); }
|
|
270
|
-
.meter span.low { background: var(--err); }
|
|
271
|
-
|
|
272
|
-
/* ---- dialogs -------------------------------------------------------- */
|
|
273
|
-
dialog { border: 1px solid var(--ink); border-radius: var(--radius); padding: 1.25rem 1.4rem;
|
|
274
|
-
width: min(40rem, calc(100vw - 2rem)); max-height: calc(100vh - 2rem);
|
|
275
|
-
background: var(--paper-2); color: var(--ink); box-shadow: 6px 6px 0 var(--ink); }
|
|
276
|
-
dialog::backdrop { background: color-mix(in oklab, var(--ink-deep) 45%, transparent); }
|
|
277
|
-
dialog h2 { margin: 0 0 .2rem; font-size: 1.375rem; font-weight: 700; }
|
|
278
|
-
:is(dialog, .form-panel) .served { color: var(--muted); font-size: .9375rem; margin: 0 0 .9rem; overflow-wrap: anywhere; }
|
|
279
|
-
:is(dialog, .form-panel) label.field { display: block; font-weight: 500; font-size: .9375rem; margin: .9rem 0 .3rem; }
|
|
280
|
-
:is(dialog, .form-panel) input:not([type=checkbox]):not([type=radio]), :is(dialog, .form-panel) select, :is(dialog, .form-panel) textarea {
|
|
281
|
-
width: 100%; font: inherit; padding: .45rem .6rem; color: var(--ink);
|
|
282
|
-
border: 1px solid var(--muted); border-radius: var(--radius); background: var(--paper-2); }
|
|
283
|
-
:is(dialog, .form-panel) .rules { font-size: .875rem; color: var(--muted); margin: .35rem 0 0; }
|
|
284
|
-
:is(dialog, .form-panel) label.check { display: flex; align-items: center; gap: .5rem; margin-top: 1rem; cursor: pointer; }
|
|
285
|
-
:is(dialog, .form-panel) fieldset { border: 0; padding: 0; margin: 1rem 0 0; }
|
|
286
|
-
:is(dialog, .form-panel) .members { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0 1rem;
|
|
287
|
-
max-height: 14rem; overflow: auto; }
|
|
288
|
-
:is(dialog, .form-panel) .members label.check { margin-top: .35rem; font-size: .875rem; }
|
|
289
|
-
:is(dialog, .form-panel) input.member-filter { font-size: .9375rem; padding: .4rem .6rem; margin-bottom: .2rem; }
|
|
290
|
-
:is(dialog, .form-panel) .members input:disabled + span { color: var(--muted); }
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
:is(dialog, .form-panel) .
|
|
294
|
-
:is(dialog, .form-panel) .
|
|
295
|
-
:is(dialog, .form-panel) .
|
|
296
|
-
:is(dialog, .form-panel) .
|
|
297
|
-
:is(dialog, .form-panel) .
|
|
298
|
-
:is(dialog, .form-panel) .
|
|
299
|
-
|
|
300
|
-
:is(dialog, .form-panel)
|
|
301
|
-
:is(dialog, .form-panel)
|
|
302
|
-
:is(dialog, .form-panel) .
|
|
303
|
-
:is(dialog, .form-panel) .
|
|
304
|
-
:is(dialog, .form-panel) .
|
|
305
|
-
.form-panel .
|
|
306
|
-
:is(dialog, .form-panel) .
|
|
307
|
-
:is(dialog, .form-panel)
|
|
308
|
-
:is(dialog, .form-panel)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
:
|
|
317
|
-
|
|
318
|
-
.
|
|
319
|
-
.
|
|
320
|
-
|
|
321
|
-
/*
|
|
322
|
-
.
|
|
323
|
-
.
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
.
|
|
327
|
-
|
|
328
|
-
.
|
|
329
|
-
|
|
330
|
-
.pick
|
|
331
|
-
.
|
|
332
|
-
.
|
|
333
|
-
.
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
/*
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
.oq-chip
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
.oq-chip
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
ul.oq-list
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
ol.steps
|
|
372
|
-
ol.steps li
|
|
373
|
-
ol.steps li
|
|
374
|
-
|
|
375
|
-
ol.steps
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
.
|
|
390
|
-
.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
.
|
|
396
|
-
|
|
397
|
-
.
|
|
398
|
-
|
|
399
|
-
.
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
.
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
.
|
|
407
|
-
.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
.
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
.
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
1
|
+
/* Benchwarmers. The theme's colour tokens arrive first (ui/themes/*.css, the
|
|
2
|
+
Wendell Research palette by default, emitted by serve.py); the values below
|
|
3
|
+
are derived from them: grounds mixed from a theme colour, and the bench's
|
|
4
|
+
own spacing. A theme sets colours only. */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
--ok: var(--primary);
|
|
8
|
+
--ok-ground: color-mix(in oklab, var(--primary) 13%, var(--paper-2));
|
|
9
|
+
--warn-ground: color-mix(in oklab, var(--signal) 55%, var(--paper-2));
|
|
10
|
+
--err-ground: color-mix(in oklab, var(--err) 11%, var(--paper-2));
|
|
11
|
+
--quiet-ground: var(--band);
|
|
12
|
+
--panel: var(--paper-2);
|
|
13
|
+
--step-1: color-mix(in oklab, var(--band) 55%, var(--paper));
|
|
14
|
+
color-scheme: var(--scheme, light);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
* { box-sizing: border-box; }
|
|
18
|
+
[hidden] { display: none !important; }
|
|
19
|
+
html { -webkit-text-size-adjust: 100%; }
|
|
20
|
+
body {
|
|
21
|
+
margin: 0;
|
|
22
|
+
/* A theme may draw the page's ground (Hardwood's maple court) and a line
|
|
23
|
+
across the top (its crimson court line); the others are plain paper. */
|
|
24
|
+
background: var(--floor, var(--paper));
|
|
25
|
+
border-top: .4rem solid var(--court-line, transparent);
|
|
26
|
+
color: var(--ink);
|
|
27
|
+
font: 400 1rem/1.55 var(--font-display);
|
|
28
|
+
-webkit-font-smoothing: antialiased;
|
|
29
|
+
}
|
|
30
|
+
::selection { background: var(--signal); color: var(--ink); }
|
|
31
|
+
a { color: var(--link); text-underline-offset: .18em; }
|
|
32
|
+
:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; border-radius: 2px; }
|
|
33
|
+
code, .mono, td.num, .chip, .alias {
|
|
34
|
+
font-family: var(--font-mono);
|
|
35
|
+
font-variant-numeric: tabular-nums;
|
|
36
|
+
}
|
|
37
|
+
code { font-size: .875em; background: var(--step-1); padding: .05rem .3rem; border-radius: var(--radius); }
|
|
38
|
+
h1, h2, h3 { line-height: 1.1; letter-spacing: -.02em; text-wrap: balance; }
|
|
39
|
+
|
|
40
|
+
/* ---- header --------------------------------------------------------- */
|
|
41
|
+
/* The page is wider than the theme's reading measure: with a sidebar, a
|
|
42
|
+
76rem page left a narrow column and wide empty margins on a large screen.
|
|
43
|
+
Prose inside panels keeps its own measure (.panel > .sub). */
|
|
44
|
+
/* One line: the name on its bench, the credit beside it, the actions pushed
|
|
45
|
+
to the far end. */
|
|
46
|
+
header {
|
|
47
|
+
max-width: var(--page, 104rem); margin: 0 auto;
|
|
48
|
+
padding: 1.5rem var(--gutter) 1rem;
|
|
49
|
+
display: flex; flex-wrap: wrap; align-items: center; column-gap: 1.25rem;
|
|
50
|
+
}
|
|
51
|
+
header h1 { margin: 0; font-size: 2.25rem; font-weight: 800; letter-spacing: -.04em; line-height: 1; }
|
|
52
|
+
/* The name sits on a team bench: a seat in the team's colour (the theme's
|
|
53
|
+
brand, or --bench-seat) on two legs joined by a rail. Drawn in CSS from the
|
|
54
|
+
font size, so it scales with the heading. With line-height 1 the letters
|
|
55
|
+
end about .14em above the box, so the seat's top is put there: the name
|
|
56
|
+
rests on it. */
|
|
57
|
+
header h1 span { position: relative; display: inline-block; padding: 0 .14em .6em; }
|
|
58
|
+
header h1 span::after { /* the seat */
|
|
59
|
+
content: ""; position: absolute; left: -.08em; right: -.08em; bottom: .46em; height: .28em;
|
|
60
|
+
background: var(--bench-seat, var(--brand)); border-radius: .06em;
|
|
61
|
+
box-shadow: inset 0 .055em 0 rgb(255 255 255 / .28), 0 .05em 0 rgb(0 0 0 / .3);
|
|
62
|
+
}
|
|
63
|
+
header h1 span::before { /* legs and the rail between them */
|
|
64
|
+
--leg: var(--bench-leg, var(--ink-2));
|
|
65
|
+
content: ""; position: absolute; left: .18em; right: .18em; bottom: 0; height: .5em;
|
|
66
|
+
background:
|
|
67
|
+
linear-gradient(var(--leg), var(--leg)) left top / .11em 100% no-repeat,
|
|
68
|
+
linear-gradient(var(--leg), var(--leg)) right top / .11em 100% no-repeat,
|
|
69
|
+
linear-gradient(var(--leg), var(--leg)) center 66% / 100% .07em no-repeat;
|
|
70
|
+
}
|
|
71
|
+
/* The credit at the bench's feet: level with the bottom of the name's group. */
|
|
72
|
+
header .sub { align-self: flex-end; margin: 0 auto 0 -.6rem; line-height: 1; color: var(--muted); font-size: .9375rem; }
|
|
73
|
+
header .sub a { color: var(--ink); font-weight: 500; text-decoration-color: var(--brand); }
|
|
74
|
+
/* Right-aligned, on the name's line or, when it does not fit, on its own. */
|
|
75
|
+
.head-actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center;
|
|
76
|
+
margin-left: auto; justify-content: flex-end; }
|
|
77
|
+
|
|
78
|
+
/* ---- buttons -------------------------------------------------------- */
|
|
79
|
+
button { font: inherit; cursor: pointer; }
|
|
80
|
+
.btn {
|
|
81
|
+
display: inline-flex; align-items: center; gap: .4rem;
|
|
82
|
+
padding: .5rem .9rem; border-radius: var(--radius);
|
|
83
|
+
border: 1px solid var(--ink); background: var(--panel); color: var(--ink);
|
|
84
|
+
font-weight: 500; font-size: .9375rem;
|
|
85
|
+
transition: transform .15s ease, box-shadow .15s ease, background-color .15s ease;
|
|
86
|
+
}
|
|
87
|
+
.btn:hover { background: var(--step-1); }
|
|
88
|
+
.btn.primary { background: var(--ink); color: var(--paper); box-shadow: 4px 4px 0 var(--brand); }
|
|
89
|
+
.btn.primary:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--brand); background: var(--ink); }
|
|
90
|
+
.btn.danger { background: var(--err); border-color: var(--err); color: var(--on-err, #fff); }
|
|
91
|
+
.btn.danger:hover { background: color-mix(in oklab, var(--err) 86%, #000); }
|
|
92
|
+
.btn.small { padding: .25rem .6rem; font-size: .875rem; }
|
|
93
|
+
.btn:disabled { opacity: .5; cursor: default; transform: none; box-shadow: none; }
|
|
94
|
+
.btn.fresh { background: var(--signal); border-color: var(--ink); }
|
|
95
|
+
.btn.fresh:hover { background: var(--signal); transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--ink); }
|
|
96
|
+
.linkish { background: none; border: 0; padding: 0; color: var(--link); text-decoration: underline;
|
|
97
|
+
text-underline-offset: .18em; font-size: inherit; }
|
|
98
|
+
|
|
99
|
+
/* ---- layout --------------------------------------------------------- */
|
|
100
|
+
main { max-width: var(--page, 104rem); margin: 0 auto; padding: 0 var(--gutter) 4rem; }
|
|
101
|
+
|
|
102
|
+
/* problems: what needs a person, each with the action that resolves it */
|
|
103
|
+
.problems { background: var(--sheet, var(--panel)); border-radius: 14px; padding: 1rem 1.4rem; margin: .5rem 0 1.5rem;
|
|
104
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 12px 32px -14px rgb(0 0 0 / .14);
|
|
105
|
+
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
106
|
+
.problems h2 { margin: 0 0 .25rem; font-size: 1.25rem; font-weight: 700; }
|
|
107
|
+
.problems > p { margin: 0 0 .5rem; color: var(--muted); font-size: .9375rem; }
|
|
108
|
+
.problem { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .25rem 1rem;
|
|
109
|
+
align-items: center; padding: .55rem .75rem; margin: 0 -.75rem; border-radius: var(--radius); }
|
|
110
|
+
.problem:hover { background: var(--step-1); }
|
|
111
|
+
.problems details { margin-top: .5rem; }
|
|
112
|
+
.problems details > summary { cursor: pointer; font-weight: 500; padding: .4rem 0; }
|
|
113
|
+
.problems details > summary .muted { font-weight: 400; }
|
|
114
|
+
.problem .what { font-weight: 500; }
|
|
115
|
+
.problem .why { color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
116
|
+
.problem .acts, .endpoint .acts, .ep .acts { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: flex-end; }
|
|
117
|
+
.row-input { display: flex; gap: .5rem; align-items: center; margin-top: .35rem; }
|
|
118
|
+
.row-input input { flex: 1; min-width: 0; margin: 0 !important; }
|
|
119
|
+
.sub-head { font-weight: 600; margin: 1rem 0 .25rem; }
|
|
120
|
+
.problem .chip { margin-right: .4rem; }
|
|
121
|
+
.problems .head { display: flex; align-items: baseline; gap: .5rem; }
|
|
122
|
+
.problems .head h2 { margin-bottom: .25rem; }
|
|
123
|
+
.problems .sep { display: none; color: var(--muted); }
|
|
124
|
+
/* Hidden (bench.js): one line, "Action needed · 3 · show", until something new */
|
|
125
|
+
.problems.collapsed { padding: .5rem 1.25rem; }
|
|
126
|
+
.problems.collapsed > :not(.head) { display: none; }
|
|
127
|
+
.problems.collapsed .head h2 { margin: 0; font-size: 1rem; }
|
|
128
|
+
.problems.collapsed .sep { display: inline; }
|
|
129
|
+
|
|
130
|
+
/* pages: a grouped sidebar (Observe, Gateway, Control); the group names and
|
|
131
|
+
the active page carry the theme's brand colour. A theme with a floor backs
|
|
132
|
+
the sidebar with frosted cream (--rail) so it reads over the court. On a
|
|
133
|
+
narrow screen the groups sit in a row above the page. */
|
|
134
|
+
.layout { display: grid; grid-template-columns: 12rem minmax(0, 1fr); gap: 1.5rem; align-items: start; }
|
|
135
|
+
.tabs { position: sticky; top: 1rem; display: flex; flex-direction: column; gap: 1.1rem;
|
|
136
|
+
background: var(--rail, transparent); padding: var(--rail-pad, 0); border-radius: 14px;
|
|
137
|
+
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
138
|
+
.tabs .group { display: flex; flex-direction: column; align-items: flex-start; gap: .55rem; }
|
|
139
|
+
.tabs h2 { margin: 0 0 .2rem; font-size: .75rem; font-weight: 700; letter-spacing: .08em;
|
|
140
|
+
text-transform: uppercase; color: color-mix(in oklab, var(--brand) 72%, var(--ink)); }
|
|
141
|
+
/* the brand, pulled toward the ink so small text stays legible in any theme */
|
|
142
|
+
/* No bottom padding and a tight line height, so the box ends just under the
|
|
143
|
+
letters; the spacing between pages is the group's gap instead. */
|
|
144
|
+
.tabs button { background: none; border: 0; padding: 0; line-height: 1.15; color: var(--muted); text-align: left;
|
|
145
|
+
font-size: 1rem; font-weight: 500; }
|
|
146
|
+
.tabs button:hover { color: var(--ink); }
|
|
147
|
+
/* The active page: a highlighter stroke across the bottom of its letters,
|
|
148
|
+
the header's old mark. */
|
|
149
|
+
.tabs button[aria-selected="true"] { color: var(--ink); font-weight: 700;
|
|
150
|
+
box-shadow: inset 0 -.42em 0 var(--signal); }
|
|
151
|
+
/* Collections, the bench's own idea: a small brand sparkle after it. It
|
|
152
|
+
hangs outside the button, so the active page's stroke still runs under
|
|
153
|
+
the word alone. */
|
|
154
|
+
.tabs button[data-tab="collections"] { position: relative; }
|
|
155
|
+
.tabs button[data-tab="collections"]::after {
|
|
156
|
+
content: ""; position: absolute; left: calc(100% + .3em); top: -.05em; width: .75em; height: .75em;
|
|
157
|
+
background: var(--brand);
|
|
158
|
+
clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
|
|
159
|
+
.tab { display: none; } .tab.active { display: block; }
|
|
160
|
+
/* One surface for the page's content: its panels are sections of it,
|
|
161
|
+
divided by a hairline, rather than separate boxes with gaps between. A
|
|
162
|
+
theme with a floor makes it frosted (--sheet, --glass). */
|
|
163
|
+
.panes { background: var(--sheet, var(--panel)); border-radius: 14px;
|
|
164
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 12px 32px -14px rgb(0 0 0 / .14);
|
|
165
|
+
-webkit-backdrop-filter: var(--glass, none); backdrop-filter: var(--glass, none); }
|
|
166
|
+
.panes .panel { background: transparent; border-radius: 0; padding: 1.4rem 1.6rem 1.5rem; }
|
|
167
|
+
.panes .tab > .panel + .panel { border-top: 1px solid var(--line); }
|
|
168
|
+
@media (max-width: 52rem) {
|
|
169
|
+
.layout { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
|
|
170
|
+
.tabs { position: static; flex-direction: row; flex-wrap: wrap; gap: .5rem 1.5rem; }
|
|
171
|
+
.tabs .group { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: .1rem 1rem; }
|
|
172
|
+
.tabs h2 { margin: 0; }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* settings, connections, logs, info */
|
|
176
|
+
.themes { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .75rem; }
|
|
177
|
+
td.set-by { font-size: .8125rem; color: var(--muted); white-space: nowrap; }
|
|
178
|
+
.theme-card { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: .35rem .5rem;
|
|
179
|
+
padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer; }
|
|
180
|
+
.theme-card:has(input:checked) { border-color: var(--ink); box-shadow: 3px 3px 0 var(--brand); }
|
|
181
|
+
.theme-card .swatch, .theme-card a { grid-column: 2; }
|
|
182
|
+
.swatch { display: flex; gap: 2px; }
|
|
183
|
+
.swatch span { width: 1rem; height: 1rem; border-radius: 2px; border: 1px solid var(--line); }
|
|
184
|
+
.theme-card a { font-size: .8125rem; }
|
|
185
|
+
table.facts th { text-align: left; padding-right: 1.5rem; color: var(--muted); font-weight: 500; }
|
|
186
|
+
details.panel > summary { cursor: pointer; }
|
|
187
|
+
details.panel[open] > summary { margin-bottom: .75rem; }
|
|
188
|
+
.log-line { font-size: .8125rem; padding: .1rem 0; overflow-wrap: anywhere; }
|
|
189
|
+
|
|
190
|
+
.panel { background: var(--panel); border-radius: var(--radius); padding: 1.1rem 1.25rem 1.25rem; }
|
|
191
|
+
.panel > h2 { margin: 0; font-size: 1.375rem; font-weight: 700; }
|
|
192
|
+
/* A section's heading carries a short bar of the brand colour: the accent a
|
|
193
|
+
mostly-white theme needs, and a marker where sections meet on one surface. */
|
|
194
|
+
.panes .panel > h2::before { content: ""; display: inline-block; width: .22em; height: .8em; margin-right: .45em;
|
|
195
|
+
vertical-align: -.05em; border-radius: 2px; background: var(--brand); }
|
|
196
|
+
.panel > .sub { margin: .3rem 0 1rem; color: var(--muted); font-size: .9375rem; max-width: 70ch; }
|
|
197
|
+
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.25rem; margin: 0 0 .75rem; }
|
|
198
|
+
.toolbar input[type=search] { font: inherit; font-size: .9375rem; padding: .4rem .6rem; min-width: 14rem;
|
|
199
|
+
border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); color: var(--ink); }
|
|
200
|
+
.toolbar label { font-size: .9375rem; display: inline-flex; align-items: center; gap: .4rem; cursor: pointer; }
|
|
201
|
+
.toolbar select { font: inherit; font-size: .9375rem; padding: .35rem .4rem; border: 1px solid var(--line);
|
|
202
|
+
border-radius: var(--radius); background: var(--paper); color: var(--ink); }
|
|
203
|
+
tr.pick-row { cursor: pointer; }
|
|
204
|
+
a.dmodel { color: var(--ink); text-decoration: none; font-weight: 500; }
|
|
205
|
+
a.dmodel:hover .alias { box-shadow: inset 0 -.3em 0 var(--signal); }
|
|
206
|
+
/* Connections: each endpoint, its models folded under it */
|
|
207
|
+
.ep { padding: .75rem 0; border-top: 1px solid var(--line); }
|
|
208
|
+
.ep-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .4rem 1rem; align-items: center; }
|
|
209
|
+
.ep .base { color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
210
|
+
.ep details.models > summary { cursor: pointer; color: var(--link); font-size: .9375rem; margin-top: .3rem; }
|
|
211
|
+
.ep details.models[open] > summary { margin-bottom: .5rem; }
|
|
212
|
+
.hint { color: var(--muted); font-size: .875rem; margin: .9rem 0 0; max-width: 75ch; }
|
|
213
|
+
|
|
214
|
+
/* key: folded until asked for */
|
|
215
|
+
details.key { margin: 1rem 0 0; }
|
|
216
|
+
details.key > summary { cursor: pointer; color: var(--link); font-size: .9375rem; width: max-content; }
|
|
217
|
+
details.key dl { margin: .5rem 0 0; display: grid; grid-template-columns: max-content minmax(0, 60ch);
|
|
218
|
+
gap: .35rem 1rem; font-size: .9375rem; }
|
|
219
|
+
details.key dt { font-weight: 700; }
|
|
220
|
+
details.key dd { margin: 0; color: var(--ink); }
|
|
221
|
+
|
|
222
|
+
/* ---- tables --------------------------------------------------------- */
|
|
223
|
+
.scroll { overflow-x: auto; }
|
|
224
|
+
table { border-collapse: collapse; width: 100%; font-size: .9375rem; }
|
|
225
|
+
th, td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
|
|
226
|
+
th { font-size: .875rem; font-weight: 700; color: var(--ink); white-space: nowrap; }
|
|
227
|
+
th[data-sortable] { cursor: pointer; user-select: none; }
|
|
228
|
+
th[data-sortable]::after { content: ""; display: inline-block; width: .9em; color: var(--muted); }
|
|
229
|
+
th[aria-sort=ascending]::after { content: " \2191"; }
|
|
230
|
+
th[aria-sort=descending]::after { content: " \2193"; }
|
|
231
|
+
td.num, th.num { text-align: right; }
|
|
232
|
+
/* the per-connection model cards on Connections: one fixed column plan */
|
|
233
|
+
table.model-cards { table-layout: fixed; min-width: 52rem; }
|
|
234
|
+
.panel:has(> table.model-cards) { overflow-x: auto; } /* scrolls on a narrow window instead of wrapping numbers */
|
|
235
|
+
table.model-cards td.num { white-space: nowrap; }
|
|
236
|
+
table.model-cards col.c-model { width: 24%; }
|
|
237
|
+
table.model-cards col.c-via { width: 13%; }
|
|
238
|
+
table.model-cards col.c-n { width: 10%; }
|
|
239
|
+
table.model-cards col.c-input { width: 19%; }
|
|
240
|
+
table.model-cards col.c-lim { width: 6%; }
|
|
241
|
+
table.model-cards td { overflow-wrap: anywhere; }
|
|
242
|
+
tbody tr:hover > td { background: var(--step-1); }
|
|
243
|
+
tr.retired > td { color: var(--muted); }
|
|
244
|
+
tr.retired .alias { text-decoration: line-through; }
|
|
245
|
+
body:not(.show-retired) tr.retired { display: none; }
|
|
246
|
+
body:not(.show-paid) tr.paid { display: none; }
|
|
247
|
+
.muted { color: var(--muted); }
|
|
248
|
+
.ok { color: var(--ok); } .warn { color: var(--warn); } .err { color: var(--err); }
|
|
249
|
+
|
|
250
|
+
a.model { color: var(--ink); text-decoration: none; font-weight: 500; }
|
|
251
|
+
a.model:hover .alias { box-shadow: inset 0 -.3em 0 var(--signal); }
|
|
252
|
+
.conn { display: block; color: var(--muted); font-size: .8125rem; }
|
|
253
|
+
|
|
254
|
+
/* status chips */
|
|
255
|
+
.chip { display: inline-block; padding: .1rem .5rem; border-radius: 999px; font-size: .8125rem;
|
|
256
|
+
font-weight: 500; white-space: nowrap; background: var(--quiet-ground); color: var(--muted); }
|
|
257
|
+
.chip.ok { background: var(--ok-ground); color: var(--primary-deep); }
|
|
258
|
+
.chip.warn { background: var(--warn-ground); color: var(--ink); }
|
|
259
|
+
.chip.err { background: var(--err-ground); color: var(--err); }
|
|
260
|
+
.chip.new { background: var(--sky); color: var(--ink-deep); }
|
|
261
|
+
/* an endpoint a model is reached through: outlined, so it reads as a place, not a state */
|
|
262
|
+
.chip.via { background: transparent; border: 1px solid var(--line); color: var(--ink); font-family: var(--font-mono); }
|
|
263
|
+
button.chip { font-family: inherit; border: 0; cursor: pointer; }
|
|
264
|
+
button.chip:hover { outline: 1px solid currentColor; }
|
|
265
|
+
|
|
266
|
+
/* helped bar: share of judged offloads that helped */
|
|
267
|
+
.helped { display: inline-flex; align-items: center; gap: .5rem; }
|
|
268
|
+
.meter { width: 4.5rem; height: .5rem; background: var(--band); border-radius: 999px; overflow: hidden; }
|
|
269
|
+
.meter span { display: block; height: 100%; background: var(--brand); }
|
|
270
|
+
.meter span.low { background: var(--err); }
|
|
271
|
+
|
|
272
|
+
/* ---- dialogs -------------------------------------------------------- */
|
|
273
|
+
dialog { border: 1px solid var(--ink); border-radius: var(--radius); padding: 1.25rem 1.4rem;
|
|
274
|
+
width: min(40rem, calc(100vw - 2rem)); max-height: calc(100vh - 2rem);
|
|
275
|
+
background: var(--paper-2); color: var(--ink); box-shadow: 6px 6px 0 var(--ink); }
|
|
276
|
+
dialog::backdrop { background: color-mix(in oklab, var(--ink-deep) 45%, transparent); }
|
|
277
|
+
dialog h2 { margin: 0 0 .2rem; font-size: 1.375rem; font-weight: 700; }
|
|
278
|
+
:is(dialog, .form-panel) .served { color: var(--muted); font-size: .9375rem; margin: 0 0 .9rem; overflow-wrap: anywhere; }
|
|
279
|
+
:is(dialog, .form-panel) label.field { display: block; font-weight: 500; font-size: .9375rem; margin: .9rem 0 .3rem; }
|
|
280
|
+
:is(dialog, .form-panel) input:not([type=checkbox]):not([type=radio]), :is(dialog, .form-panel) select, :is(dialog, .form-panel) textarea {
|
|
281
|
+
width: 100%; font: inherit; padding: .45rem .6rem; color: var(--ink);
|
|
282
|
+
border: 1px solid var(--muted); border-radius: var(--radius); background: var(--paper-2); }
|
|
283
|
+
:is(dialog, .form-panel) .rules { font-size: .875rem; color: var(--muted); margin: .35rem 0 0; }
|
|
284
|
+
:is(dialog, .form-panel) label.check { display: flex; align-items: center; gap: .5rem; margin-top: 1rem; cursor: pointer; }
|
|
285
|
+
:is(dialog, .form-panel) fieldset { border: 0; padding: 0; margin: 1rem 0 0; }
|
|
286
|
+
:is(dialog, .form-panel) .members { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0 1rem;
|
|
287
|
+
max-height: 14rem; overflow: auto; }
|
|
288
|
+
:is(dialog, .form-panel) .members label.check { margin-top: .35rem; font-size: .875rem; }
|
|
289
|
+
:is(dialog, .form-panel) input.member-filter { font-size: .9375rem; padding: .4rem .6rem; margin-bottom: .2rem; }
|
|
290
|
+
:is(dialog, .form-panel) .members input:disabled + span { color: var(--muted); }
|
|
291
|
+
/* Ruled out by the collection's tags (bench.js applyTags): greyed; a ticked
|
|
292
|
+
one stays tickable and is marked, so it can be taken off. */
|
|
293
|
+
:is(dialog, .form-panel) .members label.check.blocked:not(.clash) { cursor: not-allowed; }
|
|
294
|
+
:is(dialog, .form-panel) .members label.check.clash span { color: var(--warn); }
|
|
295
|
+
:is(dialog, .form-panel) .limits { display: flex; flex-wrap: wrap; gap: .3rem .8rem; margin-top: .3rem; font-size: .875rem; }
|
|
296
|
+
:is(dialog, .form-panel) .limits input { width: 6.5rem !important; padding: .2rem .4rem !important; }
|
|
297
|
+
:is(dialog, .form-panel) .facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
|
|
298
|
+
:is(dialog, .form-panel) .facts .src { font-size: .75rem; color: var(--muted); }
|
|
299
|
+
:is(dialog, .form-panel) .profile { margin-top: .9rem; display: grid; gap: .3rem; font-size: .875rem; }
|
|
300
|
+
:is(dialog, .form-panel) .profile .chip { margin-right: .25rem; }
|
|
301
|
+
:is(dialog, .form-panel) .profile .src { font-size: .75rem; color: var(--muted); }
|
|
302
|
+
:is(dialog, .form-panel) .settings { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
|
|
303
|
+
@media (max-width: 40rem) { :is(dialog, .form-panel) .settings { grid-template-columns: minmax(0, 1fr); } }
|
|
304
|
+
:is(dialog, .form-panel) fieldset label.check { margin-top: .4rem; flex-wrap: wrap; }
|
|
305
|
+
:is(dialog, .form-panel) fieldset label.check .muted { font-size: .875rem; }
|
|
306
|
+
:is(dialog, .form-panel) .errors { color: var(--err); font-size: .9375rem; margin: .8rem 0 0; }
|
|
307
|
+
:is(dialog, .form-panel) .done { color: var(--ok); font-size: .9375rem; margin: .8rem 0 0; }
|
|
308
|
+
:is(dialog, .form-panel) .actions { display: flex; gap: .6rem; justify-content: flex-end; margin-top: 1.25rem; flex-wrap: wrap; }
|
|
309
|
+
.form-panel .actions { justify-content: flex-start; } /* on a page, a form's button sits under its fields */
|
|
310
|
+
:is(dialog, .form-panel) .note { background: var(--step-1); border-radius: var(--radius); padding: .6rem .75rem; font-size: .9375rem; margin-top: .75rem; }
|
|
311
|
+
:is(dialog, .form-panel) details.remove { margin-top: 1.25rem; padding-top: .75rem; border-top: 1px solid var(--line); }
|
|
312
|
+
:is(dialog, .form-panel) details.remove > summary { cursor: pointer; color: var(--err); }
|
|
313
|
+
|
|
314
|
+
/* endpoints */
|
|
315
|
+
.endpoint { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .2rem 1rem; align-items: center;
|
|
316
|
+
padding: .5rem .75rem; margin: 0 -.75rem; border-radius: var(--radius); }
|
|
317
|
+
.endpoint:hover { background: var(--step-1); }
|
|
318
|
+
.endpoint .base { color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
319
|
+
:is(dialog, .form-panel) h3.form-head { margin: 1.25rem 0 0; font-size: 1rem; font-weight: 700; }
|
|
320
|
+
:is(dialog, .form-panel) input[readonly] { background: var(--step-1); }
|
|
321
|
+
/* Add an endpoint's choices: API key, then each provider; the chosen one pressed */
|
|
322
|
+
.choices { display: flex; flex-wrap: wrap; gap: .5rem; margin: .2rem 0 .4rem; }
|
|
323
|
+
.choices .btn[aria-pressed="true"] { border-color: var(--ink); box-shadow: 3px 3px 0 var(--brand); font-weight: 600; }
|
|
324
|
+
|
|
325
|
+
/* onboarding picker */
|
|
326
|
+
.picker { max-height: 22rem; overflow: auto; margin-top: .6rem; border-top: 1px solid var(--line); }
|
|
327
|
+
.picker details.grp { margin: 0; color: inherit; }
|
|
328
|
+
.picker .grp > summary { position: sticky; top: 0; z-index: 1; padding: .5rem 0 .3rem; font-weight: 700;
|
|
329
|
+
background: var(--paper-2); color: var(--muted); }
|
|
330
|
+
.pick { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .6rem; align-items: center;
|
|
331
|
+
padding: .35rem .25rem; border-radius: var(--radius); cursor: pointer; }
|
|
332
|
+
.pick:hover { background: var(--step-1); }
|
|
333
|
+
.pick:has(input:checked) { background: var(--warn-ground); }
|
|
334
|
+
.pick .alias { overflow-wrap: anywhere; font-size: .9375rem; }
|
|
335
|
+
.pick .chip.mod { margin-left: .4rem; font-size: .75rem; vertical-align: .1em; }
|
|
336
|
+
.picker .empty { color: var(--muted); padding: 1rem 0; }
|
|
337
|
+
.picker details { margin: .5rem 0; color: var(--muted); }
|
|
338
|
+
.picker details summary { cursor: pointer; font-size: .875rem; }
|
|
339
|
+
|
|
340
|
+
/* the onboarding queue: its progress in the header, its list in the popup */
|
|
341
|
+
.oq { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: .3rem .75rem;
|
|
342
|
+
font-size: .875rem; color: var(--ink); }
|
|
343
|
+
/* Short enough to sit beside the button; the whole line is its title. */
|
|
344
|
+
.oq #oq-text { max-width: min(17rem, 100%); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
345
|
+
/* The status as a chip whose fill wipes across as models finish (bench.js
|
|
346
|
+
sets --fill), ending green, or red with one shake. */
|
|
347
|
+
.oq-chip { position: relative; isolation: isolate; overflow: hidden; display: inline-flex; align-items: center;
|
|
348
|
+
max-width: 100%; min-height: 2.1rem; padding: 0 .8rem; border: 1px solid var(--line);
|
|
349
|
+
border-radius: var(--radius); background: var(--paper-2); }
|
|
350
|
+
.oq-chip::before { content: ""; position: absolute; inset: 0 auto 0 0; z-index: -1; width: var(--fill, 0%);
|
|
351
|
+
background: color-mix(in oklab, var(--brand) 22%, var(--paper-2)); transition: width .6s ease; }
|
|
352
|
+
.oq-chip.done { border-color: var(--ok); }
|
|
353
|
+
.oq-chip.done::before { background: var(--ok-ground); }
|
|
354
|
+
.oq-chip.fail { border-color: var(--err); color: var(--err); animation: oq-shake .45s ease 1; }
|
|
355
|
+
.oq-chip.fail::before { background: var(--err-ground); }
|
|
356
|
+
@keyframes oq-shake { 20% { transform: translateX(-5px); } 45% { transform: translateX(5px); }
|
|
357
|
+
70% { transform: translateX(-3px); } 90% { transform: translateX(2px); } }
|
|
358
|
+
@media (prefers-reduced-motion: reduce) {
|
|
359
|
+
.oq-chip { animation: none; }
|
|
360
|
+
.oq-chip::before { transition: none; }
|
|
361
|
+
}
|
|
362
|
+
.oq [hidden] { display: none; }
|
|
363
|
+
ul.oq-list { list-style: none; padding: 0; margin: .75rem 0 0; display: grid; gap: .5rem;
|
|
364
|
+
max-height: 22rem; overflow: auto; }
|
|
365
|
+
ul.oq-list li { padding: .4rem .25rem; border-bottom: 1px solid var(--line); }
|
|
366
|
+
ul.oq-list .what { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
|
|
367
|
+
ul.oq-list .alias { overflow-wrap: anywhere; font-size: .9375rem; }
|
|
368
|
+
ul.oq-list small { display: block; color: var(--muted); font-size: .875rem; overflow-wrap: anywhere; }
|
|
369
|
+
|
|
370
|
+
/* onboarding progress */
|
|
371
|
+
ol.steps { list-style: none; padding: 0; margin: 1rem 0 0; display: grid; gap: .35rem; }
|
|
372
|
+
ol.steps li { display: grid; grid-template-columns: 1.4rem minmax(0, 1fr); gap: .5rem; align-items: start; color: var(--muted); }
|
|
373
|
+
ol.steps li::before { content: ""; width: .75rem; height: .75rem; margin-top: .4rem; border-radius: 999px;
|
|
374
|
+
border: 2px solid var(--muted); }
|
|
375
|
+
ol.steps li.now { color: var(--ink); font-weight: 500; }
|
|
376
|
+
ol.steps li.now::before { border-color: var(--ink); background: var(--signal); }
|
|
377
|
+
ol.steps li.done { color: var(--ink); }
|
|
378
|
+
ol.steps li.done::before { border-color: var(--brand); background: var(--brand); }
|
|
379
|
+
ol.steps li.fail::before { border-color: var(--err); background: var(--err); }
|
|
380
|
+
ol.steps small { display: block; grid-column: 2; color: var(--muted); font-weight: 400; font-size: .875rem; overflow-wrap: anywhere; }
|
|
381
|
+
pre.log { background: var(--log-ground, var(--ink-deep)); color: var(--log-ink, var(--paper));
|
|
382
|
+
font-size: .8125rem; line-height: 1.45;
|
|
383
|
+
padding: .7rem .8rem; border-radius: var(--radius); max-height: 16rem; overflow: auto;
|
|
384
|
+
white-space: pre-wrap; margin: .5rem 0 0; }
|
|
385
|
+
pre.log.answer { max-height: 40vh; }
|
|
386
|
+
|
|
387
|
+
/* Benchmarks charts (Observable Plot) */
|
|
388
|
+
.chart { margin: .5rem 0 .75rem; overflow-x: auto; }
|
|
389
|
+
.chart.muted { font-size: .875rem; }
|
|
390
|
+
h3.chart-head { font-size: 1rem; margin: 1rem 0 .2rem; }
|
|
391
|
+
/* the Collections tab: the dialog's form, kept to a readable width */
|
|
392
|
+
.panel.form-panel > :not(#c-list, table) { max-width: 46rem; }
|
|
393
|
+
/* a list of things you open (collections), with its New button above */
|
|
394
|
+
.list-actions { display: flex; align-items: center; gap: 1rem; margin: .75rem 0; flex-wrap: wrap; }
|
|
395
|
+
.list-actions .done { margin: 0; color: var(--ok); font-size: .9375rem; }
|
|
396
|
+
.list-actions .errors { color: var(--err); font-size: .9375rem; }
|
|
397
|
+
button.c-row { width: 100%; text-align: left; font: inherit; color: inherit; background: none; border: 0;
|
|
398
|
+
border-radius: var(--radius); cursor: pointer; }
|
|
399
|
+
button.c-row:hover, button.c-row:focus-visible { background: var(--step-1); }
|
|
400
|
+
.c-row .open-hint { color: var(--muted); font-size: .875rem; white-space: nowrap; }
|
|
401
|
+
/* suggested collection tags under the field */
|
|
402
|
+
.tag-picks { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .45rem; }
|
|
403
|
+
.tag-picks .chip { cursor: pointer; border: 0; font-family: inherit; }
|
|
404
|
+
.tag-picks .chip:hover { outline: 1px solid currentColor; }
|
|
405
|
+
/* a field with fixed text in front (the collection name after "bench/") */
|
|
406
|
+
.prefixed { display: flex; align-items: stretch; }
|
|
407
|
+
.prefixed .prefix { display: flex; align-items: center; padding: 0 .55rem; font-family: var(--font-mono);
|
|
408
|
+
font-size: .9375rem; color: var(--muted); background: var(--step-1);
|
|
409
|
+
border: 1px solid var(--line); border-right: 0; border-radius: var(--radius) 0 0 var(--radius); }
|
|
410
|
+
.prefixed input { flex: 1; min-width: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
|
|
411
|
+
.c-settings, .limits-block { margin-top: 1.25rem; }
|
|
412
|
+
.c-settings > summary, .limits-block > summary { cursor: pointer; }
|
|
413
|
+
.actions .spacer { flex: 1; }
|
|
414
|
+
.chart figure { margin: 0; }
|
|
415
|
+
.chart [aria-label="color-legend"], .chart div[class$="-swatches"] { font-size: .8125rem; margin-bottom: .4rem; }
|
|
416
|
+
|
|
417
|
+
dialog .pick { display: flex; gap: 1.5rem; }
|
|
418
|
+
|
|
419
|
+
@media (max-width: 40rem) {
|
|
420
|
+
header h1 { font-size: 1.75rem; }
|
|
421
|
+
.problem { grid-template-columns: minmax(0, 1fr); }
|
|
422
|
+
.problem .acts { justify-content: flex-start; }
|
|
423
|
+
.ep-head { grid-template-columns: minmax(0, 1fr); }
|
|
424
|
+
.ep .acts { justify-content: flex-start; }
|
|
425
|
+
details.key dl { grid-template-columns: minmax(0, 1fr); }
|
|
426
|
+
.toolbar input[type=search] { min-width: 0; width: 100%; }
|
|
427
|
+
}
|
|
428
|
+
@media (prefers-reduced-motion: reduce) {
|
|
429
|
+
* { transition: none !important; }
|
|
430
|
+
}
|