neiko on Discord installed a third-party plugin beside a plugin of their
own, added by its folder. Only the third-party one could be seen. Both
plugins' auth hooks name the same provider id. The host's auths() keeps
the last plugin in plugins.json for an id, as OpenCode does, so the
user's own plugin silently lost it:
- its row read "Signs in to nothing magpie can use";
- its provider was gone from the Add sheet;
- keepUnloaded could list the id a second time, from the
plugin-providers.json kept before.
A package-name clash and a display-name clash were tried as well. Both
plugins stay visible in those cases, because a folder plugin's name is
its path.
What changed:
- host.js:
- init gives each loaded plugin the ids it signs in to (provides) and,
for each id another plugin serves, that plugin's spec (servedBy).
- auths() honours plugins.json's new prefer map (id -> spec).
- Only the serving plugin's provider.models hook runs for the id.
- plugin:
- Clashes() turns provides and servedBy into {id, by, with} per spec.
- Prefer() records a pick and restarts the host.
- Remove drops the removed plugin's picks.
- Re-adding a plugin under a new spec carries its picks over.
- remove, off, options and prefer find a plugin by its exact spec
before its package name (indexOf), so acting on one plugin never
reaches another of the same package.
- keepUnloaded no longer re-adds a provider from before when another
plugin serves its id now.
- GUI:
- /api/plugins rows carry clashes, with the provider's listed name.
- POST /api/plugins/prefer {spec, provider}.
- The serving row says "{other} signs in to {name} too; this one
serves it".
- The other row says, in amber, "{name} is served by {other}, which
signs in to it too", with a "Use for {name}" button.
- New strings in zh, zh-TW, ja and de.
- CLI: `magpie plugin` prints the same lines, with the command that
fixes it, and `magpie plugin use <name> <provider>` makes the pick.
- Docs: docs/subsystems/provider-plugins.md, docs/reference.md and
site/public/docs/{,zh/,ja/}plugins.html.
What was run:
- Reproduced under a sandbox HOME with magpie web on 3562: a fake npm
plugin and a folder plugin, both on id "acme".
- Old binary: the local row had providers [] and /api/providers
listed acme twice.
- New binary: both rows carry the clash; prefer moves acme to the
folder plugin; remove clears the pick and leaves the other plugin
serving acme.
- New Go tests:
- TestTwoPluginsOneProvider, a real Bun host: Prefer, restart,
off/on and Remove.
- TestClashes, TestPluginNamedExactlyFirst and
TestKeepUnloadedLeavesAServedID.
- TestPluginsClashRows (gui) and TestPluginListSaysClash (CLI).
- Each fails when its piece is broken by hand: prefer ignored in
host.js, the keepUnloaded id check removed, name before exact spec,
Remove keeping picks, no provides, no clashes in the rows, no
prefer route.
- plugin-clash.test.cjs, in Chromium and WebKit, in en, zh, zh-TW, ja
and de, at 1100 and 560px: 22/22 pass. It times out on the old
plugins.js.
- gui-de, gui-ja, gui-zh-tw, i18n-keys and every plugin-*.test.cjs:
248 tests.
- 245 passed in the 4-wide run.
- plugin-moved-signin (webkit) failed once in that run, then passed
3/3 alone and 26/26 in a smaller 4-wide rerun.
- gofmt -l; go vet ./...; GOOS=linux and GOOS=windows go vet -tags
nogui ./...; go build ./...
- The full go test -tags nogui ./... under a temp HOME with the caches
pinned: 44 packages ok, none failed.
- After rebasing onto 05917100 (plugins.css conflict with a3a8e257's
chip rules, both kept): plugin, gui and the root plugin tests, vet on
darwin, linux and windows, and the 248 GUI tests above, all green
(248/248 this time).
Not tried: a real third-party plugin, neiko's own plugins, and Windows
beyond vet.
235 lines
17 KiB
CSS
235 lines
17 KiB
CSS
/* Plugins: the market of provider plugins, and the ones installed. */
|
|
#view-plugins { gap: 0; }
|
|
.pm-head { gap: 10px; }
|
|
.pm-mirror { display: inline-flex; align-items: center; gap: 7px; padding: 2px 0; background: none; border: 0; font: inherit; font-size: 12px; color: var(--muted); cursor: pointer; white-space: nowrap; }
|
|
.pm-mirror:hover, .pm-mirror.on { color: var(--fg); }
|
|
.pm-mirror:disabled { opacity: .6; cursor: default; }
|
|
.pm-mirror .lib-switch { width: 28px; height: 16px; }
|
|
.pm-mirror .lib-switch i { width: 12px; height: 12px; }
|
|
.pm-mirror .lib-switch.on i { transform: translateX(12px); }
|
|
.pm-find {
|
|
display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; width: min(280px, 46%);
|
|
border-radius: 8px; background: var(--pill); color: var(--muted);
|
|
box-shadow: inset 0 0 0 1px transparent; transition: box-shadow .14s var(--ease), background .14s var(--ease);
|
|
}
|
|
.pm-find:focus-within { background: var(--card); box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
|
|
.pm-find svg { flex: none; }
|
|
.pm-find input { flex: 1; min-width: 0; border: 0; outline: none; background: none; color: var(--fg); font: inherit; font-size: 12.5px; }
|
|
.pm-find input::placeholder { color: var(--faint); }
|
|
.pm-find input::-webkit-search-cancel-button { cursor: default; }
|
|
.pm-body { gap: 18px; padding: 10px 0 18px; }
|
|
|
|
/* the opening: what plugins are, and a few of the subscriptions they bring */
|
|
.pm-intro {
|
|
position: relative; overflow: hidden; display: flex; align-items: center; gap: 18px;
|
|
padding: 16px 18px; border-radius: 14px; border: 1px solid var(--line);
|
|
background:
|
|
radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--accent) 11%, transparent), transparent 60%),
|
|
var(--card);
|
|
}
|
|
.pm-introtext { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
|
|
.pm-intro h2 { margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em; text-wrap: balance; }
|
|
.pm-intro p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--fg-2); max-width: 560px; }
|
|
.pm-intro .pm-trust { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 11.5px; color: var(--muted); }
|
|
.pm-intro .pm-trust svg { flex: none; color: var(--green); }
|
|
.pm-art { flex: none; display: grid; grid-template-columns: repeat(3, 34px); gap: 8px; transform: rotate(-6deg); margin-right: 6px; }
|
|
.pm-art .pm-logo { width: 34px; height: 34px; border-radius: 10px; box-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 0 0 1px var(--line-2); background: var(--card); }
|
|
.pm-art .pm-logo:nth-child(4) { grid-column: 2; }
|
|
.pm-art .pm-logo:nth-child(odd) { transform: translateY(4px); }
|
|
|
|
/* sections of cards */
|
|
.pm-sec { display: flex; flex-direction: column; gap: 9px; }
|
|
.pm-sechead { display: flex; align-items: baseline; gap: 8px; padding: 0 2px; flex-wrap: wrap; }
|
|
.pm-sechead h3 { margin: 0; font-size: 12.5px; font-weight: 650; }
|
|
.pm-sechead span { font-size: 11.5px; color: var(--muted); }
|
|
.pm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(262px, 1fr)); gap: 10px; }
|
|
|
|
.pm-logo { flex: none; width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center; background: var(--pill); color: var(--fg-2); }
|
|
.pm-logo .ic { width: 20px; height: 20px; }
|
|
.pm-logo.big { width: 44px; height: 44px; border-radius: 12px; }
|
|
.pm-logo.big .ic { width: 25px; height: 25px; }
|
|
|
|
.pm-card {
|
|
display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 12px 12px 11px 13px;
|
|
border-radius: 12px; border: 1px solid var(--line); background: var(--card); cursor: default; outline: none;
|
|
transition: border-color .16s var(--ease), box-shadow .16s var(--ease), transform .16s var(--ease);
|
|
}
|
|
.pm-card:hover { border-color: color-mix(in srgb, var(--fg) 16%, var(--line)); box-shadow: 0 4px 14px rgba(20, 22, 30, .07); }
|
|
.pm-card:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); border-color: var(--accent); }
|
|
.pm-top { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
.pm-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
.pm-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
|
|
.pm-name b { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.pm-by { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.pm-by > span { overflow: hidden; text-overflow: ellipsis; }
|
|
.pm-verified { display: inline-flex; align-items: center; gap: 3px; color: var(--green); font-weight: 500; }
|
|
.pm-sum {
|
|
margin: 0; font-size: 12px; line-height: 1.45; color: var(--fg-2); min-height: 2.9em;
|
|
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
}
|
|
.pm-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; min-height: 18px; }
|
|
.pm-dl { display: inline-flex; align-items: center; gap: 3px; }
|
|
.pm-ver { font: var(--code-style, normal) var(--code-weight, 400) 10.5px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); color: var(--muted); }
|
|
.pm-chip { display: inline-flex; align-items: center; height: 17px; padding: 0 6px; border-radius: 5px; font-size: 10.5px; font-weight: 500; background: var(--pill); color: var(--fg-2); }
|
|
.pm-chip.up { background: var(--accent-soft); color: var(--accent); }
|
|
button.pm-chip { border: 0; font-family: inherit; cursor: pointer; }
|
|
button.pm-chip.up:hover:not(:disabled) { background: var(--accent); color: var(--accent-fg); }
|
|
button.pm-chip:disabled { cursor: default; opacity: .6; }
|
|
.pm-mw-fail { color: var(--red); }
|
|
.pm-chip.bad { background: var(--red-soft); color: var(--red); }
|
|
.pm-chip.moved { gap: 4px; background: var(--accent-soft); color: var(--accent); }
|
|
.pm-chip.moved .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
|
.pm-row .sub.ask { color: var(--fg); }
|
|
/* unofficial: a hairline and a small amber dot, quiet beside the rest
|
|
of the line (yetone: 这些配色有点丑,一点都不优雅精致) */
|
|
.pm-chip.warn { gap: 5px; background: none; box-shadow: inset 0 0 0 1px var(--line); color: var(--fg-2); font-weight: 400; }
|
|
.pm-chip.warn .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--amber); flex: none; }
|
|
/* a provider two installed plugins sign in to: a line that wraps, never clipped */
|
|
.pm-row .sub.pm-clash { display: block; white-space: normal; overflow: visible; overflow-wrap: anywhere; }
|
|
.pm-clash .dot { display: inline-block; width: 6px; height: 6px; margin: 0 5px 1px 0; border-radius: 50%; background: var(--faint); vertical-align: middle; }
|
|
.pm-row .sub.pm-clash.warn { color: var(--amber); }
|
|
.pm-clash.warn .dot { background: currentColor; }
|
|
.pm-foot .pm-check { display: inline-flex; align-items: center; gap: 5px; }
|
|
.pm-foot .pm-check .spin { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid currentColor; border-right-color: transparent; animation: spin .7s linear infinite; }
|
|
/* what a plugin is reads as the line's other facts do (stars, version):
|
|
its glyph and its word, no fill of its own */
|
|
.pm-chip.kind { gap: 4px; flex: none; padding: 0; background: none; color: var(--fg-2); font-weight: 400; }
|
|
.pm-chip.kind svg { flex: none; }
|
|
/* yet the two kinds part at a glance (yetone: 中间件和供应商稍微有点区分吧):
|
|
each its own hue on the glyph and word, softened toward the text;
|
|
middleware leans teal, apart from the community badge's green */
|
|
.pm-chip.kind.pv { color: color-mix(in srgb, var(--accent) 80%, var(--fg-2)); }
|
|
.pm-chip.kind.mw { color: color-mix(in srgb, color-mix(in oklch, var(--green) 60%, var(--accent)) 80%, var(--fg-2)); }
|
|
.pm-chip.soft { background: none; box-shadow: inset 0 0 0 1px var(--line); color: var(--muted); }
|
|
|
|
/* a plugin's one button */
|
|
.pm-act {
|
|
flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
|
|
height: 26px; min-width: 64px; padding: 0 12px; border-radius: 13px;
|
|
font-size: 12px; font-weight: 600; white-space: nowrap;
|
|
background: var(--pill); color: var(--fg-2); transition: background .14s var(--ease), color .14s var(--ease), filter .14s;
|
|
}
|
|
.pm-act:hover:not(:disabled) { background: var(--pill-hover); color: var(--fg); }
|
|
.pm-act.get { background: var(--accent-soft); color: var(--accent); }
|
|
.pm-act.get:hover:not(:disabled) { background: var(--accent); color: var(--accent-fg); }
|
|
.pm-act.go { background: var(--accent); color: var(--accent-fg); }
|
|
.pm-act.go:hover:not(:disabled) { filter: brightness(1.08); background: var(--accent); color: var(--accent-fg); }
|
|
.pm-act.done { background: none; color: var(--green); padding: 0 8px; min-width: 0; }
|
|
.pm-act.done:hover:not(:disabled) { background: var(--green-soft); color: var(--green); }
|
|
.pm-act.busy { color: var(--muted); font-weight: 500; }
|
|
.pm-act:disabled:not(.busy):not(.done) { opacity: .55; }
|
|
.pm-act .spin { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid currentColor; border-right-color: transparent; animation: spin .7s linear infinite; }
|
|
|
|
/* loading: cards drawn as grey bars */
|
|
.pm-card.ghost { gap: 10px; pointer-events: none; }
|
|
.pm-card.ghost > div { border-radius: 6px; background: var(--pill); animation: pm-pulse 1.3s ease-in-out infinite; }
|
|
.pm-card.ghost .g1 { height: 36px; width: 60%; }
|
|
.pm-card.ghost .g2 { height: 11px; }
|
|
.pm-card.ghost .g3 { height: 11px; width: 40%; }
|
|
@keyframes pm-pulse { 50% { opacity: .5; } }
|
|
|
|
.pm-note { margin: 0; padding: 4px 2px; font-size: 12px; color: var(--muted); }
|
|
.pm-note.bad { color: var(--red); }
|
|
.pm-note.warn { display: flex; align-items: flex-start; gap: 6px; padding: 8px 10px; border-radius: 8px; background: var(--amber-soft); color: var(--fg); line-height: 1.5; }
|
|
.pm-note.warn svg { flex: none; margin-top: 2px; color: var(--amber); }
|
|
.pm-empty { margin: 24px 4px; font-size: 12.5px; color: var(--red); }
|
|
|
|
/* a package the market doesn't list */
|
|
.pm-manual { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 12px; border: 1px dashed var(--line); flex-wrap: wrap; }
|
|
.pm-mlabel { font-size: 12px; color: var(--muted); }
|
|
.pm-minput { flex: 1; min-width: 180px; height: 26px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font: var(--code-style, normal) var(--code-weight, 400) 12px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); outline: none; }
|
|
.pm-minput:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
|
|
/* the system's folder picker, beside the field it fills */
|
|
.pm-browse { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; flex: none; padding: 0; border-radius: 7px; border: 1px solid var(--line); background: var(--card); color: var(--muted); cursor: pointer; transition: color .14s var(--ease), border-color .14s var(--ease); }
|
|
.pm-browse:hover:not(:disabled) { color: var(--fg); border-color: var(--faint); }
|
|
.pm-browse:disabled { opacity: .5; cursor: default; }
|
|
|
|
/* Installed */
|
|
.pm-listhead { margin: 0 0 -10px; padding: 0 2px; }
|
|
.pm-list .row { min-height: 54px; padding: 8px 10px 8px 12px; gap: 11px; cursor: default; transition: background .14s var(--ease); }
|
|
.pm-list .row:hover { background: var(--card-2); }
|
|
.pm-list .row + .row { border-top: 1px solid var(--line-2); }
|
|
.pm-row .pm-logo { width: 32px; height: 32px; border-radius: 9px; }
|
|
.pm-row .pm-logo .ic { width: 18px; height: 18px; }
|
|
.pm-row .who { flex: 1; min-width: 0; }
|
|
.pm-row .name { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; }
|
|
.pm-row .sub { display: flex; align-items: center; flex-wrap: wrap; gap: 0 2px; margin-top: 2px; font-size: 11.5px; color: var(--muted); }
|
|
.pm-row .sub.bad { color: var(--red); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.pm-row .sub .sep { color: var(--faint); }
|
|
.pm-sub { display: inline-flex; align-items: center; gap: 5px; }
|
|
.pm-sub .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--faint); }
|
|
.pm-sub.in .dot { background: var(--green); }
|
|
.pm-opts { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
|
|
.pm-opts textarea {
|
|
width: 100%; box-sizing: border-box; resize: vertical; padding: 8px 10px; border-radius: 8px;
|
|
border: 1px solid var(--line); background: var(--card); color: var(--fg); font: var(--code-style, normal) var(--code-weight, 400) 12px/1.5 var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); tab-size: 2; outline: none;
|
|
}
|
|
.pm-opts textarea:focus { border-color: var(--accent); }
|
|
.pm-opts-err { font-size: 11.5px; color: var(--red); }
|
|
.pm-opts-err:empty { display: none; }
|
|
.pm-opts-bar { display: flex; align-items: center; gap: 2px; }
|
|
.pm-opts-bar > span { flex: 1; min-width: 0; font-size: 11.5px; color: var(--muted); }
|
|
.pm-row .val { display: flex; align-items: center; gap: 2px; flex: none; }
|
|
.pm-row.off .who, .pm-row.off .pm-logo { opacity: .5; }
|
|
.pm-foot { display: flex; align-items: center; gap: 8px; padding: 0 4px; font-size: 11px; color: var(--faint); }
|
|
.pm-none { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 44px 16px; text-align: center; }
|
|
.pm-none b { font-size: 13.5px; font-weight: 600; margin-top: 4px; }
|
|
.pm-none p { margin: 0 0 6px; font-size: 12px; color: var(--muted); max-width: 320px; line-height: 1.5; }
|
|
|
|
/* a plugin's page */
|
|
.modal .editor.pm-detail.framed > .ehead { min-height: 76px; gap: 12px; }
|
|
.modal .editor.pm-detail.framed > .ebody { display: block; padding: 0; }
|
|
.pm-dhead .pm-name b { font-size: 15px; }
|
|
.pm-dhead .pm-by { font-size: 11.5px; }
|
|
.pm-dact .pm-act { height: 28px; min-width: 80px; border-radius: 14px; }
|
|
.pm-dbody { display: flex; flex-direction: column; gap: 12px; padding: 14px 18px 18px; }
|
|
.pm-dsum { margin: 0; font-size: 13px; line-height: 1.5; color: var(--fg); }
|
|
.pm-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 1px; border-radius: 10px; overflow: hidden; background: var(--line-2); border: 1px solid var(--line-2); }
|
|
.pm-fact { display: flex; flex-direction: column; gap: 2px; padding: 8px 11px; background: var(--card); min-width: 0; }
|
|
.pm-fact .k { font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
|
|
.pm-fact .v { font-size: 12.5px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
|
|
.pm-links { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
.pm-link { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 9px; border-radius: 7px; background: var(--pill); color: var(--fg-2); font-size: 11.5px; text-decoration: none; }
|
|
.pm-link:hover { background: var(--pill-hover); color: var(--fg); }
|
|
.pm-readme { border-top: 1px solid var(--line-2); padding-top: 12px; min-height: 60px; }
|
|
.pm-rskel { height: 11px; margin: 8px 0; border-radius: 5px; background: var(--pill); animation: pm-pulse 1.3s ease-in-out infinite; }
|
|
.pm-rskel.short { width: 55%; }
|
|
|
|
/* a README */
|
|
.pm-md { font-size: 12.5px; line-height: 1.6; color: var(--fg-2); overflow-wrap: anywhere; }
|
|
.pm-md > :first-child { margin-top: 0; }
|
|
.pm-md h3, .pm-md h4, .pm-md h5, .pm-md h6 { color: var(--fg); margin: 16px 0 6px; line-height: 1.3; text-wrap: balance; }
|
|
.pm-md h3 { font-size: 15px; font-weight: 650; }
|
|
.pm-md h4 { font-size: 13.5px; font-weight: 650; }
|
|
.pm-md h5, .pm-md h6 { font-size: 12.5px; font-weight: 600; }
|
|
.pm-md p { margin: 0 0 9px; }
|
|
.pm-md ul, .pm-md ol { margin: 0 0 9px; padding-left: 20px; }
|
|
.pm-md li + li { margin-top: 2px; }
|
|
.pm-md a { color: var(--accent); text-decoration: none; }
|
|
.pm-md a:hover { text-decoration: underline; }
|
|
.pm-md code { font: var(--code-style, normal) var(--code-weight, 400) 11.5px var(--code-font, var(--code)); font-stretch: var(--code-stretch, 100%); padding: 1px 4px; border-radius: 4px; background: var(--pill); color: var(--fg); }
|
|
.pm-md pre { margin: 0 0 10px; padding: 9px 11px; border-radius: 8px; background: var(--card-2); border: 1px solid var(--line-2); overflow-x: auto; }
|
|
.pm-md pre code { padding: 0; background: none; font-size: 11.5px; line-height: 1.35; white-space: pre; } /* close enough for a box drawn in │ and ─ to join */
|
|
.pm-md blockquote { margin: 0 0 9px; padding: 7px 11px; border-radius: 8px; background: var(--card-2); color: var(--fg-2); }
|
|
.pm-md hr { border: 0; border-top: 1px solid var(--line-2); margin: 12px 0; }
|
|
.pm-table { overflow-x: auto; margin: 0 0 10px; }
|
|
.pm-md table { border-collapse: collapse; font-size: 12px; }
|
|
.pm-md th, .pm-md td { padding: 5px 9px; border: 1px solid var(--line-2); text-align: left; vertical-align: top; }
|
|
.pm-md th { background: var(--card-2); font-weight: 600; color: var(--fg); }
|
|
|
|
/* the add sheet's row to Plugins */
|
|
.tile.more-plugins { color: var(--accent); }
|
|
.tile.more-plugins .puzzle { flex: none; width: 18px; height: 18px; display: grid; place-items: center; }
|
|
.tile.more-plugins > svg { flex: none; opacity: .7; }
|
|
.tile.more-plugins:hover { background: var(--accent-soft); }
|
|
|
|
@media (max-width: 560px) {
|
|
.pm-head { flex-wrap: wrap; }
|
|
.pm-find { width: 100%; order: 3; }
|
|
.pm-art { display: none; }
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.pm-card { transition: none; }
|
|
.pm-card.ghost > div, .pm-rskel { animation: none; }
|
|
}
|