The servers page had only By agent and the order, each with its own "In the library" heading, so with both the heading showed twice. Turning every server on or off, or removing them all, took one chip or one row at a time. The page now has one heading (lib-serverhead, which wraps when narrow) holding the order, Select, Turn all on, Turn all off, By agent and Remove all, as the skills page does. The skills page's helpers now serve both pages rather than being copied. picking names the page ("skills" or "servers"). pickingFor, pickRow, pickBar and groupChips(kind) are shared, and so are everyButtons, confirmEveryOff and everyOf, which replace everySkillButtons and everySkill. removeEveryButton, confirmRemoveEvery and removeEvery replace removeEverySkillButton. The skills page says and does what it did before.
- Turn all on and Turn all off post every agent shown to servers/agents-all (EveryServerAgents, now serversAgents(nil, …)). A hidden agent is left alone. Turn all on is greyed once every server is on for every agent that can reach it. Turn all off asks first, in the page.
- Select puts a box on each row. A row's click ticks it rather than opening the server. The bar's chips post the servers picked to the new servers/agents-some (SomeServersAgents), which gives an agent only the ones it can reach (mcpFile.supports) and leaves unnamed servers and agents as they are. An agent that can reach none of the picks has its chip greyed, with the reason.
- Remove all asks first. It says which agents lose the servers, the projects they are taken from, the sign-ins forgotten, and that the agents' own servers stay. It then posts every name to the new servers/remove-all (RemoveServers). This is one change that takes each server out as RemoveServer does: out of the library, its projects and its icon (removeServer, now shared by both), then out of every agent through syncMCP, which takes only what Applied says magpie wrote, and then forgets its sign-in. A name the library hasn't is listed in Unremoved, and the rest go all the same.
- The pick bar wraps, so its chips and Done fit at 440px in ja and de.
TestRemoveServers checks a server the user put in Claude Code's file and Codex's own "docs" of a library server's name: both stay, while fs, docs and neon leave the library, both agents and the project's .mcp.json, and the project's own "team" stays. neon's sign-in is gone, "nope" is reported, and an empty list or one with only "nope" errors. TestSomeServersAgents checks that Codex gets fs but not the SSE web, that git stays untouched, that a call naming no servers or no agents errors, and that a call naming an unknown server writes nothing. Both pass with -race -count=10, alongside TestEveryServerAgents and TestRemoveServer*.
library-servers-bulk.test.cjs passes on Chromium and WebKit in en, zh, ja and de at 440px. It checks one heading with every button, Turn all on's post without the hidden Copilot CLI, Turn all off's Cancel posting nothing and Confirm keeping Copilot CLI's, the pick bar's codex chip posting agents-some for the two picked and its greyed state for web alone, the All box, Done, and Remove all's lines, Cancel and post. It also checks for no sideways scroll and that each control clicked stays where it was on the screen. The fake check answers every server, since an unchecked one is checked again at each drawing. It fails without the change and passes 6 runs beside pick-skills, every-skill and gui-ja at --test-concurrency=4. by-agent, pick-skills, every-skill, remove-all-skills, group-*, library-*, mcp-signin, project-servers, skill-*, i18n-keys, gui-ja and gui-de pass. skill-how's WebKit case and click-scroll's "Live and a day" fail the same on the unchanged origin/main when run beside each other, and pass alone. go test -tags nogui ./internal/..., go vet, gofmt -l, and the linux (nogui) and windows builds pass. Not tried in the real app. docs/subsystems/library.md says it.
543 lines
42 KiB
CSS
543 lines
42 KiB
CSS
/* Library: instructions, MCP servers and skills for every agent. */
|
|
#view-library { gap: 0; }
|
|
/* The tabs stay at the top while the page scrolls under them, on a frosted
|
|
strip as wide as the view; a hairline shows once something is beneath. */
|
|
.lib-head {
|
|
position: sticky; top: 0; z-index: 5;
|
|
display: flex; align-items: center; gap: 8px; flex: none;
|
|
margin: 0 -12px; padding: 6px 12px 4px;
|
|
background: color-mix(in srgb, var(--bg) 92%, transparent);
|
|
-webkit-backdrop-filter: saturate(1.6) blur(16px); backdrop-filter: saturate(1.6) blur(16px);
|
|
box-shadow: 0 1px 0 transparent; transition: box-shadow .18s var(--ease);
|
|
}
|
|
/* the window's view is padded 2px at the top: the strip reaches over it */
|
|
body.window .lib-head { top: -2px; margin: -2px -16px 0; padding: 8px 16px 4px; }
|
|
@media (max-width: 760px), (pointer: coarse) and (max-width: 1024px) {
|
|
body.web .lib-head {
|
|
flex-wrap: wrap;
|
|
margin: -2px calc(-1 * var(--view-right)) 0 calc(-1 * var(--view-left));
|
|
padding: 8px var(--view-right) 4px var(--view-left);
|
|
}
|
|
body.web .lib-tabs { max-width: 100%; flex-wrap: wrap; }
|
|
body.web .lib-more { flex: none; }
|
|
}
|
|
.lib-head.stuck { box-shadow: 0 1px 0 var(--line-2); }
|
|
.lib-tabs .opt { height: 24px; padding: 0 12px; font-size: 12.5px; }
|
|
.lib-more { display: inline-flex; align-items: center; gap: 5px; }
|
|
.lib-mini { display: inline-grid; place-items: center; color: var(--muted); }
|
|
.lib-mini svg { width: 13px; height: 13px; }
|
|
.lib-body { display: flex; flex-direction: column; flex: none; }
|
|
.lib-body.enter { animation: content-in .22s var(--ease); }
|
|
.lib-intro { margin: 8px 2px 10px; font-size: 12px; line-height: 1.5; color: var(--muted); max-width: 640px; }
|
|
.lib-aside { margin: 8px 4px 0; font-size: 11.5px; line-height: 1.5; color: var(--faint); }
|
|
.lib-aside.center { text-align: center; margin-top: 14px; }
|
|
.lib-foot { margin: auto 0 0; padding: 18px 4px 6px; font-size: 11px; color: var(--faint); flex: none; }
|
|
.lib-link { font-size: 11px; color: var(--muted); text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 2px; }
|
|
.lib-link:hover { color: var(--fg); text-decoration-color: currentColor; }
|
|
|
|
/* the glyph at the front of a row: drawn, in the text colour */
|
|
.lib-glyph { flex: none; width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center; color: var(--fg-2); background: var(--pill); }
|
|
.lib-glyph svg { width: 15px; height: 15px; }
|
|
.lib-rtk-logo .mask { width: 20px; height: 20px; background: currentColor; -webkit-mask: var(--i) center / contain no-repeat; mask: var(--i) center / contain no-repeat; }
|
|
.mk-icon.lib-logo { flex: none; width: 26px; height: 26px; border-radius: 7px; }
|
|
.lib-editor .ehead .mk-icon.lib-logo { width: 24px; height: 24px; }
|
|
|
|
/* cards: the shared text, the skill finder */
|
|
.lib-card { display: flex; flex-direction: column; }
|
|
.lib-cardhead { display: flex; align-items: center; gap: 9px; padding: 9px 12px 0; }
|
|
.lib-cardhead b { font-weight: 600; font-size: 13px; }
|
|
.lib-cardhead .note { font-size: 11px; color: var(--faint); }
|
|
.lib-text {
|
|
display: block; width: 100%; box-sizing: border-box; resize: none; border: 0; outline: none; background: none; color: var(--fg);
|
|
padding: 10px 14px 14px; font: var(--code-style, normal) var(--code-weight, 400) 12.5px/1.6 var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); tab-size: 2; min-height: 150px;
|
|
}
|
|
.lib-text::placeholder { color: var(--faint); font-family: var(--ui-font, var(--font)); font-size: 12.5px; }
|
|
:where(html[data-fonts]) .lib-text::placeholder { font-style: var(--ui-style, inherit); font-weight: var(--ui-weight, inherit); font-stretch: var(--ui-stretch, 100%); }
|
|
.lib-text.small { min-height: 64px; border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; background: var(--card); transition: border-color .12s, box-shadow .12s; }
|
|
.lib-text.small:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
|
|
|
|
/* unsaved text: a bar that stays in view at the bottom until it's saved */
|
|
.lib-savebar {
|
|
position: sticky; bottom: 8px; z-index: 3; margin-top: 12px; display: flex; align-items: center; gap: 6px;
|
|
padding: 7px 8px 7px 14px; border-radius: 11px; background: var(--pop-bg); box-shadow: var(--shadow);
|
|
-webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); animation: lib-rise .22s var(--ease);
|
|
}
|
|
.lib-savebar[hidden] { display: none; }
|
|
.lib-savebar .note { font-size: 12px; color: var(--fg-2); display: inline-flex; align-items: center; gap: 7px; }
|
|
.lib-savebar .note::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--fg); }
|
|
@keyframes lib-rise { from { opacity: 0; transform: translateY(8px); } }
|
|
|
|
/* rows */
|
|
.lib-list .row { min-height: 50px; padding: 7px 10px 7px 12px; gap: 11px; }
|
|
.lib-row.click { cursor: default; transition: background .14s var(--ease); }
|
|
.lib-row.click:hover { background: var(--card-2); }
|
|
/* a long name, link or description breaks anywhere rather than pushing
|
|
the row wider than the list (#257) */
|
|
.lib-row .who { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
|
|
/* and beside a hand of many agents' chips it keeps room to be read (#936) */
|
|
.lib-row.with-agents > .who { min-width: min(140px, 32%); }
|
|
/* a server's or skill's picture sits level with the top of its name */
|
|
.lib-row > .lib-logo, .lib-row > .lib-glyph { align-self: flex-start; margin-top: 1px; }
|
|
.lib-row .name.mono, .lib-pick .name.mono { font: var(--code-style, normal) 500 12.5px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); }
|
|
.lib-row .sub { max-width: 100%; }
|
|
.lib-row .sub.mono, .lib-pick .sub.mono { font: var(--code-style, normal) var(--code-weight, 400) 11px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--muted); }
|
|
.lib-row .chev { flex: none; color: var(--faint); transition: transform .2s var(--ease); display: grid; place-items: center; }
|
|
.lib-row.open .chev { transform: rotate(90deg); }
|
|
.lib-row.open { background: var(--card-2); }
|
|
.lib-skill .sub { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.4; }
|
|
.lib-skill.missing .name { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--faint); }
|
|
.lib-skill.missing .sub { color: var(--amber); }
|
|
.lib-src { display: flex; align-items: center; gap: 5px; margin-top: 3px; font-size: 11px; color: var(--faint); min-width: 0; }
|
|
/* "linked from" stays whole, one line, and the path beside it gives way:
|
|
CJK can break after any character, so the label shrank to a column of
|
|
them and the row, a fixed height in a long list, lost its name (#257) */
|
|
.lib-src > span { flex: none; white-space: nowrap; }
|
|
.lib-src > .lib-path, .lib-src > .lib-srclink { flex: 0 1 auto; min-width: 0; }
|
|
.lib-srclink { font: var(--code-style, normal) var(--code-weight, 400) 11px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--muted); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.lib-srclink:hover { color: var(--fg); text-decoration: underline; text-underline-offset: 2px; }
|
|
|
|
/* a path: shown in the file manager on a click */
|
|
.lib-path { font: var(--code-style, normal) var(--code-weight, 400) 11px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--muted); padding: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; border-radius: 3px; }
|
|
.lib-path:hover { color: var(--fg); text-decoration: underline; text-underline-offset: 2px; }
|
|
|
|
/* tags beside a name */
|
|
.lib-tags { display: flex; gap: 5px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
|
|
.lib-tag { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px; border-radius: 6px; font-size: 11px; color: var(--fg-2); background: var(--pill); white-space: nowrap; }
|
|
.lib-tag.warn { color: var(--amber); background: var(--amber-soft); }
|
|
.lib-tag.warn::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
|
/* what a check for updates found, beside a skill's name */
|
|
.lib-row .name .lib-tag { height: 17px; padding: 0 6px; margin-left: 7px; font-size: 10.5px; font-weight: 500; vertical-align: 1px; }
|
|
.lib-tag.lib-new { color: var(--accent); background: var(--accent-soft); }
|
|
.lib-tag.lib-new::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
|
.lib-tag.lib-new.link { cursor: pointer; }
|
|
.lib-tag.lib-new.link:hover { background: color-mix(in srgb, var(--accent) 22%, var(--accent-soft)); }
|
|
.lib-tag.lib-unchecked { color: var(--faint); font-weight: 400; }
|
|
.lib-tag.lib-signed { color: var(--green); background: var(--green-soft); }
|
|
.lib-tag.lib-signed::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
|
|
|
/* magpie's sign-in to a remote server, in its editor (#615) */
|
|
.lib-signin-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 28px; }
|
|
.lib-signin-line .note { font-size: 12px; color: var(--fg-2); }
|
|
.lib-signin-err { margin-top: 6px; font-size: 12px; color: var(--red); line-height: 1.45; overflow-wrap: anywhere; }
|
|
|
|
/* the switch */
|
|
.lib-switch { flex: none; position: relative; width: 32px; height: 19px; border-radius: 10px; background: var(--line); transition: background .2s var(--ease); }
|
|
.lib-switch i { position: absolute; top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: transform .22s var(--ease); }
|
|
.lib-switch.on { background: var(--fg); }
|
|
.lib-switch.on i { transform: translateX(13px); background: var(--card); }
|
|
:root[data-theme="dark"] .lib-switch.on i { background: var(--bg); }
|
|
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .lib-switch.on i { background: var(--bg); } }
|
|
|
|
/* the sets of shared instructions: a radio picks the one the agents read */
|
|
.lib-sets .lib-cardhead { padding-bottom: 8px; }
|
|
.lib-radio { flex: none; width: 17px; height: 17px; border-radius: 50%; border: 1.5px solid var(--faint); display: grid; place-items: center; transition: border-color .14s; }
|
|
.lib-radio:hover { border-color: var(--fg-2); }
|
|
.lib-radio.on { border-color: var(--fg); }
|
|
.lib-radio.on::after { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--fg); }
|
|
.lib-set.on .name { font-weight: 600; }
|
|
.lib-sets .lib-detail { padding-left: 40px; }
|
|
.lib-sets > .lib-cardhead + .row, .lib-sets .lib-detail + .row, .lib-sets .lib-detail + .lib-setadd, .lib-sets .row + .lib-setadd { border-top: 1px solid var(--line-2); }
|
|
.lib-setadd { padding: 8px 10px 10px; }
|
|
input.lib-setname { height: 28px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); font-size: 12.5px; outline: none; max-width: 280px; transition: border-color .12s, box-shadow .12s; }
|
|
input.lib-setname.grow { flex: 1 1 auto; max-width: none; }
|
|
input.lib-setname:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
|
|
|
|
/* an agent's instructions, opened */
|
|
.lib-detail { padding: 4px 14px 14px 50px; background: var(--card-2); display: flex; flex-direction: column; gap: 8px; border-top: 0 !important; animation: content-in .2s var(--ease); }
|
|
.lib-lab { font-size: 11.5px; color: var(--muted); }
|
|
.lib-detail .lib-aside { margin: 0; }
|
|
.lib-acts { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
.lib-warn { font-size: 12px; line-height: 1.5; color: var(--fg); background: var(--amber-soft); border-radius: 8px; padding: 8px 10px; }
|
|
.lib-warn .lib-path { display: inline; }
|
|
/* what the last change couldn't write: for which agent, and why */
|
|
.lib-problems { flex: none; margin: 8px 0 6px; padding: 9px 12px 10px; border-radius: 10px; background: var(--amber-soft); color: var(--fg); font-size: 12px; line-height: 1.45; min-width: 0; overflow-wrap: anywhere; }
|
|
.lib-problems-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
.lib-problems-head b { font-weight: 600; min-width: 0; }
|
|
.lib-problems-head .action { flex: none; }
|
|
.lib-problems-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--amber); }
|
|
.lib-problems ul { list-style: none; margin: 6px 0 0; padding: 0 0 0 15px; display: grid; gap: 4px; }
|
|
.lib-problems li { min-width: 0; }
|
|
.lib-problems-sep { color: var(--muted); }
|
|
.lib-problems-err { display: block; color: var(--fg-2); font: var(--code-style, normal) var(--code-weight, 400) 11px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); margin-top: 1px; }
|
|
.lib-problems-fix { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
|
|
|
|
/* agents a server or skill is given to: an icon each, lit when it has it */
|
|
.lib-agents { display: flex; flex-wrap: wrap; gap: 3px; flex: none; justify-content: flex-end; max-width: 50%; }
|
|
.lib-ag {
|
|
position: relative; display: inline-flex; align-items: center; gap: 6px; height: 26px; min-width: 26px; padding: 0 5px; border-radius: 7px;
|
|
border: 1px solid transparent; font-size: 12px; color: var(--muted); transition: background .14s, border-color .14s, color .14s, transform .14s var(--ease);
|
|
}
|
|
.lib-ag .ic { width: 15px; height: 15px; filter: grayscale(1); opacity: .35; transition: filter .14s, opacity .14s; }
|
|
.lib-ag:hover { background: var(--pill); }
|
|
.lib-ag:hover .ic { opacity: .7; }
|
|
.lib-ag.on { background: var(--card); border-color: var(--line); color: var(--fg); box-shadow: 0 1px 1px rgba(0, 0, 0, .05); }
|
|
.lib-ag.on .ic { filter: none; opacity: 1; }
|
|
/* an icon made grey once rather than through the filter on every paint
|
|
(library.js, greyIcon): a picture's grey copy stands in for it, and one
|
|
drawn in the text's colour takes that colour grey — the same pixels.
|
|
The copy is hidden wherever the icon goes, not only in a chip: an
|
|
agent's icon is copied from one made once (agentIcon), grey copy and
|
|
all, into the rows of what agents have of their own too */
|
|
.ic > img.grey { display: none; }
|
|
.lib-ag:not(.on) .ic.baked { filter: none; }
|
|
.lib-ag:not(.on) .ic.baked > img:not(.grey) { display: none; }
|
|
.lib-ag:not(.on) .ic.baked > img.grey { display: block; }
|
|
@supports (color: rgb(from currentColor r g b)) {
|
|
.lib-ag:not(.on) .ic.flat { filter: none; color: rgb(from currentColor calc(r * .2126 + g * .7152 + b * .0722) calc(r * .2126 + g * .7152 + b * .0722) calc(r * .2126 + g * .7152 + b * .0722)); }
|
|
}
|
|
.lib-ag.via { border: 1px dashed var(--line); }
|
|
.lib-ag.via .ic { opacity: .6; }
|
|
.lib-ag.warn::after { content: ""; position: absolute; top: -2px; right: -2px; width: 7px; height: 7px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 0 2px var(--card); }
|
|
.lib-ag.blocked { opacity: .35; }
|
|
.lib-ag.blocked:hover { background: none; }
|
|
.lib-ag:active:not(.blocked) { transform: scale(.92); }
|
|
.editor .lib-agents { max-width: none; justify-content: flex-start; gap: 5px; }
|
|
.editor .lib-ag { padding: 0 9px 0 6px; border-color: var(--line); }
|
|
.editor .lib-ag.on { background: var(--accent-soft); border-color: color-mix(in srgb, var(--fg) 30%, transparent); }
|
|
.lib-probefoot .lib-agents { max-width: none; justify-content: flex-start; }
|
|
|
|
/* in a list row they sit stacked like a hand of cards, on one line, and fan
|
|
out when the pointer or focus comes to them */
|
|
.lib-row > .lib-agents { flex-wrap: nowrap; gap: 0; max-width: none; padding-left: 4px; }
|
|
/* Reserve the spread width between All and the icons. As the gaps grow,
|
|
this spacer shrinks by the same amount, keeping All and the row in place. */
|
|
.lib-row > .lib-agents::before { content: ""; order: 1; flex: none; width: max(0px, calc((var(--lib-agent-count, 1) - 1) * 10px)); transition: width .22s var(--ease); }
|
|
.lib-row > .lib-agents:hover::before, .lib-row > .lib-agents:focus-within::before { width: 0; }
|
|
.lib-row > .lib-agents .lib-ag[data-agent] { order: 2; }
|
|
.lib-row > .lib-agents .lib-ag { flex: none; width: 24px; min-width: 0; height: 24px; padding: 0 0 0 4px; justify-content: flex-start; background: var(--card); border-color: var(--line-2); box-shadow: none; transition: margin .22s var(--ease), background .14s, border-color .14s, transform .14s var(--ease); }
|
|
.lib-row > .lib-agents .lib-ag .ic { width: 14px; height: 14px; }
|
|
/* the ring in the card's colour that cuts each chip out of the one under
|
|
it: an outline rather than a spread shadow, the same ring cheaper to
|
|
paint; a chip with the focus shows the focus ring instead */
|
|
.lib-row > .lib-agents .lib-ag:not(:focus-visible) { outline: 1.5px solid var(--card); outline-offset: 0; }
|
|
.lib-row > .lib-agents .lib-ag + .lib-ag { margin-left: -7px; }
|
|
/* With many agents the chips close up, each further under the one before
|
|
(#936), so the hand stays in about half the row and the name beside it
|
|
keeps its room: --lib-stack is how far a chip goes under the one before,
|
|
-7px while they fit, --lib-fan the same fanned out, 3px while they fit;
|
|
the spacer before them is the difference. A WebKit without container
|
|
units keeps -7px and 3px. */
|
|
@supports (width: 1cqw) {
|
|
.lib-row.with-agents { container-type: inline-size; }
|
|
.lib-row > .lib-agents {
|
|
--lib-n: var(--lib-agent-count, 1);
|
|
--lib-gap: calc((48cqw - 60px - var(--lib-n) * 24px) / max(1, var(--lib-n) - 1));
|
|
--lib-stack: clamp(-19px, var(--lib-gap), -7px);
|
|
--lib-fan: clamp(var(--lib-stack), var(--lib-gap), 3px);
|
|
}
|
|
.lib-row > .lib-agents::before { width: max(0px, calc((var(--lib-n) - 1) * (var(--lib-fan) - var(--lib-stack)))); }
|
|
.lib-row > .lib-agents .lib-ag + .lib-ag { margin-left: var(--lib-stack); }
|
|
}
|
|
.lib-row > .lib-agents .lib-ag.on { border-color: var(--line); box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
|
|
.lib-row > .lib-agents .lib-ag.via { border-style: dashed; }
|
|
.lib-row > .lib-agents:hover .lib-ag[data-agent] + .lib-ag[data-agent], .lib-row > .lib-agents:focus-within .lib-ag[data-agent] + .lib-ag[data-agent] { margin-left: 3px; }
|
|
@supports (width: 1cqw) {
|
|
.lib-row > .lib-agents:hover .lib-ag[data-agent] + .lib-ag[data-agent], .lib-row > .lib-agents:focus-within .lib-ag[data-agent] + .lib-ag[data-agent] { margin-left: var(--lib-fan); }
|
|
}
|
|
.lib-row > .lib-agents:hover .lib-ag, .lib-row > .lib-agents:focus-within .lib-ag { box-shadow: none; }
|
|
.lib-row > .lib-agents:hover .lib-ag:not(:focus-visible), .lib-row > .lib-agents:focus-within .lib-ag:not(:focus-visible) { outline-color: transparent; }
|
|
.lib-row > .lib-agents .lib-ag:hover { background: var(--pill); z-index: 1; }
|
|
.lib-row.click:hover > .lib-agents .lib-ag { box-shadow: none; }
|
|
.lib-row.click:hover > .lib-agents .lib-ag:not(:focus-visible) { outline-color: var(--card-2); }
|
|
.lib-row.click:hover > .lib-agents:hover .lib-ag:not(:focus-visible) { outline-color: transparent; }
|
|
/* All, ahead of the hand: a word, apart from the chips it lights */
|
|
.lib-row > .lib-agents .lib-ag.all { width: auto; padding: 0 7px; margin-right: 6px; justify-content: center; font-size: 11px; font-weight: 500; color: var(--muted); }
|
|
.lib-row > .lib-agents .lib-ag.all.on { color: var(--fg); }
|
|
.lib-row > .lib-agents .lib-ag.all + .lib-ag { margin-left: 0; }
|
|
|
|
/* agents that have one of their own, not in the library */
|
|
.lib-have { display: flex; gap: 4px; flex: none; }
|
|
.lib-have .ic { width: 15px; height: 15px; }
|
|
|
|
/* a skill's actions show on hover */
|
|
.lib-rowacts { display: flex; gap: 2px; flex: none; opacity: 0; transition: opacity .14s; }
|
|
.lib-row:hover .lib-rowacts, .lib-rowacts:focus-within { opacity: 1; }
|
|
.lib-icon { width: 26px; height: 26px; padding: 0; display: inline-grid; place-items: center; }
|
|
.lib-icon.busy svg { animation: lib-bob .8s var(--ease) infinite alternate; }
|
|
@keyframes lib-bob { to { transform: translateY(-2px); } }
|
|
|
|
/* the skill finder */
|
|
.lib-install { margin-bottom: 4px; }
|
|
.lib-find { display: flex; align-items: center; gap: 8px; padding: 8px 8px 8px 12px; }
|
|
.lib-find input { flex: 1; min-width: 0; height: 28px; border: 0; outline: none; background: none; font-size: 13px; color: var(--fg); }
|
|
.lib-find input::placeholder { color: var(--faint); }
|
|
.lib-find .text.busy { color: var(--muted); }
|
|
.lib-err { padding: 0 14px 10px 36px; font-size: 12px; color: var(--red); line-height: 1.45; overflow-wrap: anywhere; }
|
|
.lib-probe { border-top: 1px solid var(--line-2); padding: 8px 8px 8px; display: flex; flex-direction: column; gap: 6px; animation: content-in .22s var(--ease); }
|
|
.lib-probehead { display: flex; align-items: center; gap: 6px; padding: 0 4px; }
|
|
.lib-probehead .note { font-size: 11.5px; color: var(--muted); }
|
|
.lib-filter { height: 26px; margin: 0 4px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 12px; outline: none; }
|
|
.lib-filter:focus { border-color: var(--accent); }
|
|
.lib-picks { display: flex; flex-direction: column; max-height: 300px; overflow-y: auto; }
|
|
.lib-pick { display: flex; align-items: flex-start; gap: 10px; padding: 7px 6px; border-radius: 8px; cursor: default; }
|
|
.lib-pick:hover:not(.dim) { background: var(--pill); }
|
|
.lib-pick.dim { opacity: .55; }
|
|
.lib-pick input { margin: 2px 0 0; accent-color: var(--fg); flex: none; }
|
|
.lib-pick .who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
.lib-pick .name { font-size: 13px; font-weight: 500; }
|
|
.lib-pick .sub { font-size: 11.5px; color: var(--muted); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
.lib-probefoot { display: flex; align-items: center; gap: 8px; padding: 8px 4px 0; border-top: 1px solid var(--line-2); flex-wrap: wrap; }
|
|
.lib-probefoot .note { font-size: 12px; color: var(--muted); }
|
|
|
|
/* nothing yet */
|
|
.lib-empty { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 34px 20px 30px; text-align: center; background: var(--card); border: 1px dashed var(--line); border-radius: 12px; }
|
|
.lib-empty b { font-weight: 600; font-size: 13px; }
|
|
.lib-empty p { margin: 0 0 8px; font-size: 12px; color: var(--muted); max-width: 380px; line-height: 1.5; }
|
|
.lib-none { padding: 14px; font-size: 12px; color: var(--muted); }
|
|
/* the page in outline while the library loads: it comes in only after a
|
|
moment, so a quick load goes straight to the page; one sweep of light
|
|
runs across every bar at once */
|
|
.lib-skel { animation: lib-skel-in .3s var(--ease) .18s both; }
|
|
@keyframes lib-skel-in { from { opacity: 0; } }
|
|
.lib-skel .skeleton { background-color: var(--skel, var(--pill)); background-attachment: fixed; background-size: 200vw 100%; background-repeat: no-repeat; background-position: 20vw 0; animation-name: lib-skel-shift; animation-duration: 1.8s; }
|
|
@keyframes lib-skel-shift { from { background-position: 20vw 0; } to { background-position: -100vw 0; } }
|
|
.lib-skel .who { display: flex; flex-direction: column; gap: 7px; }
|
|
.lib-skel .lib-sk-icon { flex: none; border-radius: 7px; }
|
|
.lib-skel .lib-sk-switch { flex: none; border-radius: 10px; margin-right: 22px; } /* the chevron after it */
|
|
.lib-skel .lib-sk-intro { height: 18px; display: flex; align-items: center; }
|
|
.lib-skel .row-head .skeleton { border-radius: 4px; }
|
|
@media (prefers-reduced-motion: reduce) { .lib-skel, .lib-skel .skeleton { animation: none; } }
|
|
|
|
/* the dialog */
|
|
.lib-editor .ehead .lib-glyph { width: 24px; height: 24px; }
|
|
.lib-editor .ehead .note { font-size: 11.5px; color: var(--faint); margin-left: auto; }
|
|
.lib-editor .lib-slot { display: contents; }
|
|
.lib-editor .lib-grid { display: contents; }
|
|
.lib-editor input.mono { font-family: var(--code-font, var(--code)); font-size: 12px; }
|
|
:where(html[data-fonts]) .lib-editor input.mono { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
|
|
.lib-pairs { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
|
|
.lib-pair { display: flex; gap: 6px; width: 100%; align-items: center; }
|
|
.lib-pair input { flex: 1; min-width: 0; font-family: var(--code-font, var(--code)); font-size: 12px; }
|
|
:where(html[data-fonts]) .lib-pair input { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
|
|
.lib-pair input:first-child { flex: .8; }
|
|
.lib-x { width: 24px; height: 24px; padding: 0; display: inline-grid; place-items: center; flex: none; }
|
|
.lib-addpair { padding-left: 0; }
|
|
.lib-addpair:hover { background: none; }
|
|
.lib-editor .lib-picks { grid-column: 1 / -1; max-height: 320px; }
|
|
.lib-editor .lib-keep { grid-column: 1 / -1; margin: 0 -6px; }
|
|
.lib-confirm { grid-column: 1 / -1; margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--fg-2); }
|
|
.text.danger-fill { background: var(--red); color: #fff; }
|
|
/* one agent's skills or servers on or off at once (#475) */
|
|
.lib-byagent-sheet .lib-byagent-list { grid-column: 1 / -1; max-height: min(52vh, 420px); overflow: auto; }
|
|
.lib-byagent-row { gap: 10px; }
|
|
.lib-byagent-row > .ic { width: 20px; height: 20px; flex: none; }
|
|
.lib-byagent-row .who { flex: 1; min-width: 0; }
|
|
.lib-byagent-row .name { display: flex; align-items: center; gap: 6px; }
|
|
.lib-byagent-row .lib-updall { height: 24px; padding: 0 9px; font-size: 12px; flex: none; }
|
|
.lib-byagent-row .lib-updall:disabled { color: var(--faint); cursor: default; }
|
|
/* how the agents are given their skills (#896) */
|
|
.lib-skillhow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 12px 0 14px; }
|
|
.lib-skillhow .label { font-size: 12px; color: var(--fg-2); }
|
|
.lib-skillhow .segs { align-self: center; }
|
|
.lib-skillhow .lib-updall { height: 24px; padding: 0 9px; font-size: 12px; }
|
|
.lib-skillhow .note { font-size: 11px; color: var(--faint); line-height: 1.45; min-width: 0; flex: 1 0 100%; margin-top: -4px; }
|
|
.lib-how-row .segs { flex: none; align-self: center; }
|
|
.lib-reader { grid-template-columns: minmax(0, 1fr); }
|
|
.lib-md { margin: 0; max-height: min(60vh, 520px); overflow: auto; font: var(--code-style, normal) var(--code-weight, 400) 12px/1.6 var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--fg-2); white-space: pre-wrap; overflow-wrap: anywhere; background: var(--card-2); border-radius: 8px; padding: 12px 14px; user-select: text; -webkit-user-select: text; }
|
|
.lib-reader .bar .lib-path { max-width: 70%; }
|
|
.editor .editor-error:empty { display: none; }
|
|
|
|
@media (max-width: 560px) {
|
|
.lib-list .row { flex-wrap: wrap; }
|
|
.lib-agents { max-width: 100%; }
|
|
}
|
|
|
|
/* a list's heading: its label, and a quiet line of what it does */
|
|
#view-library .row-head { height: auto; min-height: 26px; margin: 18px 0 6px; padding: 0 2px; gap: 12px; }
|
|
#view-library .row-head .note { min-width: 0; font-size: 11px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
#view-library .row-head .lib-updall { height: 24px; padding: 0 9px; font-size: 12px; }
|
|
/* every skill out of the library at once (#449): red from the start */
|
|
#view-library .row-head .lib-everyrm { color: var(--red); }
|
|
#view-library .row-head .lib-everyrm:hover { background: var(--red-soft); }
|
|
|
|
/* the market: servers and skills to add, each with its own picture */
|
|
.mk { display: flex; flex-direction: column; }
|
|
.mk-find { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; margin-bottom: 10px; border-radius: 10px; background: var(--card); border: 1px solid var(--line); transition: border-color .14s, box-shadow .14s; }
|
|
.mk-find:focus-within { border-color: color-mix(in srgb, var(--fg) 35%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fg) 7%, transparent); }
|
|
.mk-find input { flex: 1; min-width: 0; height: 100%; border: 0; outline: none; background: none; font-size: 13px; color: var(--fg); }
|
|
.mk-find input::placeholder { color: var(--faint); }
|
|
.mk-find input::-webkit-search-cancel-button { -webkit-appearance: none; }
|
|
.mk-spin { flex: none; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--line); border-top-color: var(--fg-2); opacity: 0; transition: opacity .15s; }
|
|
.mk.loading .mk-spin { opacity: 1; animation: mk-spin .7s linear infinite; }
|
|
@keyframes mk-spin { to { transform: rotate(360deg); } }
|
|
.mk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(236px, 1fr)); gap: 10px; transition: opacity .2s var(--ease); }
|
|
.mk.loading .mk-grid { opacity: .55; }
|
|
.mk-card {
|
|
position: relative; display: flex; flex-direction: column; gap: 9px; min-width: 0; padding: 12px 12px 10px; border-radius: 12px;
|
|
background: var(--card); border: 1px solid var(--line); box-shadow: 0 1px 1px rgba(0, 0, 0, .03);
|
|
transition: border-color .16s var(--ease), box-shadow .16s var(--ease), transform .16s var(--ease);
|
|
animation: content-in .24s var(--ease) both;
|
|
}
|
|
.mk-card.click:hover { border-color: color-mix(in srgb, var(--fg) 22%, transparent); box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .18); transform: translateY(-1px); }
|
|
.mk-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
.mk-icon {
|
|
flex: none; width: 36px; height: 36px; border-radius: 9px; overflow: hidden; display: grid; place-items: center;
|
|
background: #fff; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
|
|
}
|
|
.mk-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
.mk-icon.svg img { width: 72%; height: 72%; object-fit: contain; }
|
|
.mk-icon.mono { background: var(--pill); box-shadow: none; }
|
|
.mk-mono { font-size: 15px; font-weight: 600; color: var(--fg-2); }
|
|
.mk-icon.skeleton { box-shadow: none; }
|
|
:root[data-theme="dark"] .mk-icon:not(.mono):not(.skeleton) { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); }
|
|
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .mk-icon:not(.mono):not(.skeleton) { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); } }
|
|
.mk-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
|
|
.mk-name { display: flex; align-items: center; gap: 5px; min-width: 0; font-size: 13px; font-weight: 600; line-height: 1.2; }
|
|
.mk-title { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.mk-name.big { font-size: 15px; }
|
|
.mk-meta { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11px; color: var(--muted); }
|
|
.mk-pub { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.mk-badge { flex: none; display: inline-flex; align-items: center; gap: 3px; height: 17px; padding: 0 6px; border-radius: 5px; background: var(--pill); color: var(--fg-2); font-size: 10.5px; font-family: var(--code-font, var(--code)); }
|
|
:where(html[data-fonts]) .mk-badge { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
|
|
.mk-badge.mk-needs { width: 17px; padding: 0; justify-content: center; }
|
|
.mk-official { flex: none; display: inline-grid; place-items: center; width: 13px; height: 13px; border-radius: 50%; background: var(--fg); color: var(--card); }
|
|
.mk-desc { margin: 0; min-height: 2.9em; font-size: 12px; line-height: 1.45; color: var(--fg-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
.mk-desc.wait { background: linear-gradient(90deg, var(--pill) 25%, var(--pill-hover) 45%, var(--pill) 65%); background-size: 240% 100%; animation: skeleton-shift 1.4s ease-in-out infinite; border-radius: 5px; min-height: 0; height: 8px; margin: 6px 20% 10px 0; }
|
|
.mk-foot { display: flex; align-items: center; gap: 8px; min-height: 26px; margin-top: auto; }
|
|
.mk-id { min-width: 0; font: var(--code-style, normal) var(--code-weight, 400) 11px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.mk-installs { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
.mk-add { flex: none; height: 26px; }
|
|
.mk-add.busy { color: var(--muted); }
|
|
.mk-have { flex: none; display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 4px; font-size: 12px; color: var(--muted); }
|
|
.mk-card.have .mk-icon { opacity: .9; }
|
|
.mk-msg { grid-column: 1 / -1; padding: 22px 12px; text-align: center; font-size: 12px; color: var(--muted); }
|
|
.mk-msg.mk-custom { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 12px; padding: 14px 12px; overflow-wrap: anywhere; }
|
|
.mk-msg.err { padding: 8px 12px; color: var(--amber); background: var(--amber-soft); border-radius: 8px; text-align: left; line-height: 1.45; }
|
|
.mk-skel { gap: 12px; min-height: 104px; }
|
|
.mk-skel .mk-who { gap: 7px; }
|
|
|
|
/* a market item up close */
|
|
.mk-sheet .mk-sheethead { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--line-2); }
|
|
.mk-sheet .mk-icon { width: 44px; height: 44px; border-radius: 11px; }
|
|
.mk-sheet .mk-about { grid-column: 1 / -1; margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--fg-2); }
|
|
.mk-sheet .mk-hint { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; margin: 0; font-size: 11.5px; color: var(--muted); }
|
|
.mk-ext { flex: none; display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); text-decoration: none; padding: 3px 6px; border-radius: 6px; }
|
|
.mk-ext:hover { color: var(--fg); background: var(--pill); }
|
|
.mk-sheet .mk-hint .mk-ext { padding: 0; font-family: var(--code-font, var(--code)); font-size: 11.5px; }
|
|
:where(html[data-fonts]) .mk-sheet .mk-hint .mk-ext { font-style: var(--code-style, inherit); font-weight: var(--code-weight, inherit); font-stretch: var(--code-stretch, 100%); }
|
|
.mk-sheet .mk-hint .mk-ext:hover { background: none; text-decoration: underline; text-underline-offset: 2px; }
|
|
.mk-sheet .bar .mk-id { margin-left: 2px; }
|
|
.lib-rtk-gain { margin: 6px 12px 10px; font-size: 12px; line-height: 1.5; color: var(--muted); }
|
|
.lib-card > .lib-acts { padding: 0 12px 12px; }
|
|
.lib-rtk-note { margin: 6px 12px 0; font-size: 12px; line-height: 1.5; color: var(--amber); }
|
|
.lib-rtk-scope { opacity: .8; }
|
|
.lib-rtk-err { color: var(--red); user-select: text; overflow-wrap: anywhere; }
|
|
.lib-rtk-chart { margin: 0 12px 12px; padding: 10px 12px 8px; }
|
|
.lib-rtk-chart .bars { height: 88px; }
|
|
.lib-rtk-foot { display: flex; align-items: center; gap: 12px; margin-top: 8px; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
.lib-rtk-foot .grow { flex: 1; }
|
|
.lib-rtk-key { display: inline-flex; align-items: center; gap: 5px; }
|
|
.lib-rtk-key i { width: 8px; height: 8px; border-radius: 2px; background: var(--accent); }
|
|
.lib-rtk-key i.in { opacity: .38; }
|
|
.lib-cardhead button.text { height: 22px; font-size: 11.5px; }
|
|
.lib-rtk-cmd { margin: -4px 12px 10px; font: var(--code-style, normal) var(--code-weight, 400) 11.5px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--muted); user-select: text; }
|
|
|
|
/* projects: a card each, its skills shown when it is opened */
|
|
.lib-project { margin-bottom: 8px; }
|
|
.lib-project.missing .lib-projhead .name { color: var(--muted); }
|
|
.lib-projhead .lib-tags { max-width: 45%; overflow: hidden; flex-wrap: nowrap; }
|
|
/* whether a server works, beside its name: a dot and a few words, the
|
|
whole reason in the tooltip; a click checks it again */
|
|
.lib-srvwho { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); align-items: center; }
|
|
.lib-srvwho > .name { min-width: 0; }
|
|
.lib-srvwho > .lib-health { justify-self: start; max-width: min(220px, 100%); }
|
|
.lib-srvwho > :not(.name):not(.lib-health) { grid-column: 1 / -1; }
|
|
.lib-health { display: inline-flex; flex: 0 1 auto; min-width: 0; align-items: center; gap: 5px; max-width: 220px; height: 17px; margin-left: 7px; padding: 0 6px; border-radius: 6px;
|
|
font: var(--ui-style, normal) 400 11px var(--ui-font, var(--font)); font-stretch: var(--ui-stretch, 100%); color: var(--muted); white-space: nowrap; transition: background .14s var(--ease); }
|
|
.lib-health > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
.lib-health[hidden] { display: none; }
|
|
.lib-health:hover { background: var(--pill); }
|
|
.lib-health::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--faint); }
|
|
.lib-health.ok::before { background: var(--green); }
|
|
.lib-health.auth { color: var(--amber); }
|
|
.lib-health.auth::before { background: var(--amber); }
|
|
.lib-health.err { color: var(--red); }
|
|
.lib-health.err::before { background: var(--red); }
|
|
.lib-health.checking::before { animation: lib-health-pulse 1s ease-in-out infinite alternate; }
|
|
@keyframes lib-health-pulse { to { opacity: .25; } }
|
|
@media (prefers-reduced-motion: reduce) { .lib-health.checking::before { animation: none; } }
|
|
.lib-tag.lib-dot::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--muted); }
|
|
.lib-projopts { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 8px 12px 8px 49px; border-top: 1px solid var(--line-2); background: var(--card-2); }
|
|
.lib-projopts .note { font-size: 11px; color: var(--faint); line-height: 1.45; min-width: 0; flex: 1 1 220px; }
|
|
.lib-projcopy { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg-2); cursor: default; }
|
|
.lib-project .lib-projskill { border-top: 1px solid var(--line-2); }
|
|
.lib-projfoot { margin: 0; padding: 8px 12px 10px 49px; border-top: 1px solid var(--line-2); }
|
|
.lib-projfoot + .lib-projfoot { border-top: 0; padding-top: 0; }
|
|
|
|
/* the library's skills: a card for each GitHub repository they came from,
|
|
and one for those on this computer, folded to its heading line */
|
|
.lib-groups { display: flex; flex-direction: column; gap: 8px; }
|
|
/* a group's head is its card's title, not one more skill (#936): shaded,
|
|
its repository in bold, its chips cut out of the shade */
|
|
.lib-row.lib-grouphead { background: var(--card-2); }
|
|
.lib-row.lib-grouphead.click:hover { background: color-mix(in srgb, var(--card-2) 70%, var(--pill)); }
|
|
.lib-grouphead .name, .lib-grouphead .name.mono { font-weight: 600; }
|
|
.lib-grouphead > .lib-agents .lib-ag:not(:focus-visible) { outline-color: var(--card-2); }
|
|
.lib-grouphead .sub { font-size: 11px; }
|
|
.lib-grouphead > .lib-logo, .lib-grouphead > .lib-glyph { align-self: center; margin-top: 0; }
|
|
.lib-grouphead .lib-updall { height: 24px; padding: 0 9px; font-size: 12px; }
|
|
/* a group's chip whose agent has some of its skills: half lit */
|
|
.lib-row > .lib-agents .lib-ag.some { border-style: dashed; border-color: var(--line); }
|
|
.lib-ag.some .ic { filter: none; opacity: .55; }
|
|
.lib-ag.some .ic.baked > img:not(.grey) { display: block; }
|
|
.lib-ag.some .ic.baked > img.grey { display: none; }
|
|
/* the skills' heading has the most on it: in a narrow window it goes on
|
|
to a second line rather than past the page's side */
|
|
#view-library .row-head.lib-skillshead, #view-library .row-head.lib-serverhead { flex-wrap: wrap; row-gap: 6px; }
|
|
#view-library .row-head.lib-skillshead .lib-skillq { flex: 1 1 90px; max-width: 190px; }
|
|
#view-library .row-head .lib-skillq { width: 190px; height: 24px; margin: 0; flex: 0 1 auto; min-width: 90px; }
|
|
.lib-skillq::-webkit-search-cancel-button { -webkit-appearance: none; }
|
|
/* a project's skills out of view are neither laid out nor painted until they near it */
|
|
.lib-projskill { content-visibility: auto; contain-intrinsic-size: auto 76px; }
|
|
.lib-grouphead .lib-rowacts { min-width: 26px; }
|
|
/* A group's skills are drawn near the view first (library.js, windowed),
|
|
room kept for the rest, which are drawn in while nothing else is going
|
|
on and then stay. Every row is held to the height the list counts on —
|
|
its description one line, the whole of it in its tooltip — so the room
|
|
kept is exactly what's missing. */
|
|
.lib-vl { flex: none; }
|
|
/* each row kept to itself, as a skipped one was; and a row the pointer
|
|
passes over in a scroll shows its buttons at once rather than fading them
|
|
in — in WebKit each fade, given a layer of its own while it ran, cost a
|
|
long frame (library.js marks a list .scrolling while it scrolls) */
|
|
.lib-vl > .row { border-top: 1px solid var(--line-2); overflow: hidden; flex-wrap: nowrap; contain: layout paint style; }
|
|
.lib-vl.scrolling > .row .lib-rowacts { transition: none; }
|
|
.lib-vl.bare > .row.first { border-top: 0; }
|
|
.lib-vl > .row.lib-skill { height: 51px; min-height: 0; padding: 7px 10px 7px 12px; gap: 11px; }
|
|
.lib-vl > .row.lib-skill.src { height: 67px; }
|
|
.lib-vl > .lib-skill .sub { display: block; white-space: nowrap; -webkit-line-clamp: none; }
|
|
.lib-vl > .lib-skill .lib-src { margin-top: 2px; }
|
|
/* a part of a group: the folder its skills sit in, or the start of their names */
|
|
.lib-vl > .row.lib-subhead { height: 36px; min-height: 0; padding: 0 12px 0 14px; gap: 8px; }
|
|
.lib-subhead { background: var(--card-2); }
|
|
.lib-subhead .name { font-size: 12px; color: var(--fg-2); }
|
|
.lib-subhead .name.mono { font: var(--code-style, normal) 500 11.5px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); }
|
|
.lib-subhead .sub { margin: 0; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
.lib-subhead .lib-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
|
|
.lib-row.lib-subhead:hover { background: color-mix(in srgb, var(--card-2) 70%, var(--pill)); }
|
|
/* no color-mix() before Safari 16.2 (#220): the sticky head stays opaque */
|
|
@supports not (color: color-mix(in srgb, red 50%, blue)) { .lib-head { background: var(--bg); } }
|
|
/* skills picked to turn on or off together (#791): a box on each row and
|
|
heading, and a bar that stays in view under the list while it's long */
|
|
.lib-pickbox { margin: 0; flex: none; }
|
|
.lib-vl > .row.lib-skill.picked { background: var(--accent-soft); }
|
|
.lib-list > .row.lib-server.picked { background: var(--accent-soft); }
|
|
.lib-pickbar { position: sticky; bottom: 12px; z-index: 3; margin-top: 8px; min-height: 44px; flex-wrap: wrap; row-gap: 6px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); box-shadow: var(--shadow); }
|
|
.lib-pickall { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg-2); white-space: nowrap; }
|
|
.lib-pickn { font-size: 12px; font-weight: 500; color: var(--fg); white-space: nowrap; }
|
|
.lib-pickn.none { font-weight: 400; color: var(--faint); white-space: normal; }
|
|
.lib-pickbar .lib-updall { height: 24px; padding: 0 9px; font-size: 12px; flex: none; }
|
|
.lib-subhead > .lib-agents { margin-left: auto; }
|
|
.lib-pickbar .lib-groupname { flex: 1 1 140px; min-width: 100px; max-width: 240px; margin: 0; }
|
|
.lib-grouphead .lib-grouprename-in { height: 24px; margin: 0; max-width: 260px; font-weight: 500; }
|
|
|
|
/* Safari before 15.4 has no :focus-visible and drops the chips' rings
|
|
above: there they go by :focus */
|
|
@supports not selector(:focus-visible) {
|
|
.lib-row > .lib-agents .lib-ag:not(:focus) { outline: 1.5px solid var(--card); outline-offset: 0; }
|
|
.lib-row > .lib-agents:hover .lib-ag:not(:focus), .lib-row > .lib-agents:focus-within .lib-ag:not(:focus) { outline-color: transparent; }
|
|
.lib-row.click:hover > .lib-agents .lib-ag:not(:focus) { outline-color: var(--card-2); }
|
|
.lib-row.click:hover > .lib-agents:hover .lib-ag:not(:focus) { outline-color: transparent; }
|
|
.lib-grouphead > .lib-agents .lib-ag:not(:focus) { outline-color: var(--card-2); }
|
|
}
|