/*
 * The pages' layout over the theme (theme.css, linked before this file): paper and ink, forest only for what a person acts on, sand only
 * for the person's own money, brick only for a failure. Every colour, face, size, leading, weight, radius, motion and space is a name the
 * theme sets, light and dark alike; this file holds none of its own, and the stylesheet test holds it to that.
 */
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body { display: flex; flex-direction: column; background: var(--ground); color: var(--ink); font-family: var(--font-ui); font-size: var(--size-body); line-height: var(--leading-body); accent-color: var(--act); }
a { color: var(--act); }
:focus-visible { outline: 2px solid var(--act); outline-offset: 2px; }
::selection { background: var(--act-wash); color: var(--ink); }
button, select, input, textarea { font: inherit; color: inherit; }
/* One button: the board's shape and size wherever a button carries a word. */
button { padding: var(--space-2) var(--space-5); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--raised); font-size: var(--size-small); line-height: var(--leading-small); cursor: pointer; }
button:hover:not(:disabled) { background: var(--hover); }
:where([data-theme="dark"]) button:hover:not(:disabled) { background: var(--float-hover); }
button.primary { border-color: var(--act); background: var(--act); color: var(--act-ink); }
button.primary:hover:not(:disabled) { border-color: var(--act-hover); background: var(--act-hover); }
/* A button that cannot be pressed: the wash and the quiet words, with no outline to press. */
button:disabled, button.primary:disabled { border-color: var(--line); background: var(--wash); color: var(--quiet); cursor: default; }
select, input { padding: var(--space-2) var(--space-4); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--raised); }
/* Strong text is the theme's strong weight, never the browser's. */
h1, h2, h3, h4, strong, b, th { font-weight: var(--weight-strong); }
pre, code { font-family: var(--font-mono); font-size: var(--size-small); line-height: var(--leading-small); }
pre { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.quiet { color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-5); margin: 0; }

.app { flex: 1; min-height: 0; display: flex; position: relative; }
.page { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; position: relative; }
/* The sidebar is the frame: a shade off the page, with its own ink, quiet words and money. */
.sidebar { display: none; flex: none; width: 15.5rem; min-height: 0; flex-direction: column; gap: var(--space-6); padding: var(--space-5) var(--space-4); border-right: 1px solid var(--frame-line); background: var(--frame); color: var(--frame-ink); font-size: var(--size-small); line-height: var(--leading-small); }
.app.sidebar-shown .sidebar { display: flex; }
.backdrop { display: none; }
/* The sidebar's opener takes a row of its own above the page, so nothing of the conversation is laid under it. */
.sidebar-open { flex: none; align-self: flex-start; margin: var(--space-4) var(--space-4) 0; padding: var(--space-1) var(--space-4); line-height: var(--leading-tight); }
.app.sidebar-shown .sidebar-open, .app.bare .sidebar-open { display: none; }
/* The opener's row has an edge like the sidebar's, so text passing under it reads as scrolling. */
.app:not(.sidebar-shown):not(.bare) .sidebar-open + main { margin-top: var(--space-4); border-top: 1px solid var(--frame-line); }
.sidebar-head { display: flex; align-items: center; justify-content: space-between; padding: 0 var(--space-3); }
.sidebar .brand { display: flex; align-items: center; gap: var(--space-4); font-size: var(--size-lead); font-weight: var(--weight-strong); line-height: var(--leading-tight); color: inherit; text-decoration: none; }
.sidebar .brand::before { content: ""; width: 1.4rem; height: 1.4rem; background: url("./assets/favicon.svg") center / contain no-repeat; }
.sidebar-close { padding: 0 var(--space-4); border: none; font-size: var(--size-lead); line-height: var(--leading-tight); background: none; color: var(--frame-quiet); }
.sidebar-close:hover:not(:disabled) { background: var(--frame-hover); color: var(--frame-ink); }
.sidebar a { color: inherit; text-decoration: none; }
.sidebar .entry { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-3); border-radius: var(--radius); }
.sidebar .entry:hover, .contents button:hover:not(:disabled), .sidebar [aria-current="page"] { background: var(--frame-hover); }
.sidebar .entry-name { font-weight: var(--weight-strong); }
.contents { flex: 1; min-height: 0; overflow-y: auto; }
.contents h2 { margin: 0; padding: 0 var(--space-3); font-size: var(--size-small); }
.contents h3 { margin: var(--space-4) 0 var(--space-1); padding: 0 var(--space-3); font-size: var(--size-caption); font-weight: var(--weight-regular); color: var(--frame-quiet); }
.contents ul { margin: 0; padding: 0; list-style: none; }
.contents button { display: block; width: 100%; padding: var(--space-2) var(--space-3); border: none; background: none; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.entries { flex: none; }
/* History: the heading and the search stay where they are and only the list scrolls under them. Nothing above the list clips, so the
   focus ring drawn outside a control has its room on every side; the list, which must clip, keeps that room inside its edges. */
.contents.history { display: flex; flex-direction: column; overflow: visible; }
.contents.history > h2, .contents.history > .history-search { flex: none; }
/* The heading is drawn as the Plugins entry is, its padding and its shade on hover. */
.contents.history > h2.head-entry { padding: 0; }
.contents.history .history-search { width: calc(100% - 2 * var(--space-2)); margin: var(--space-3) var(--space-2) var(--space-2); background: var(--raised); font-size: var(--size-small); line-height: var(--leading-small); }
.contents.history .history-search[hidden] { display: none; }
/* No clear control in the field: Escape and the keyboard clear it, and its room goes to the words. */
.contents.history .history-search::placeholder { color: var(--quiet); opacity: 1; }
.contents.history .history-search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.contents.history .history-list { flex: 1; min-height: 0; overflow-y: auto; margin: 0 calc(-1 * var(--space-2)); padding: var(--space-2); scroll-padding-block: var(--space-4); }
.contents.history .list-earlier { margin: 0 0 var(--space-5); padding: 0 var(--space-3); color: var(--frame-quiet); }
/* A title may run to two lines; a longer one ends in an ellipsis, and its whole title is the row's tooltip. */
.contents.history .history-row { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: var(--leading-small); }
/* In a search's rows a title is shown whole, so its matched words are always in view. */
.contents.history .history-row.result { display: block; }
/* The row of the messages before the first title: its name, and under it the days it holds, each on one line. */
.contents.history .history-row.untitled { display: block; }
.contents.history .history-row.untitled .row-name, .contents.history .history-row.untitled .row-days { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.contents.history .history-row.untitled .row-days { color: var(--frame-quiet); font-size: var(--size-caption); }
.contents.history p.history-row { margin: 0; padding: var(--space-2) var(--space-3); }
/* What a search found, under the search box; the list's first day heading keeps its distance from both. */
.contents.history .history-found { flex: none; margin: 0 0 var(--space-2); padding: 0 var(--space-3); color: var(--frame-quiet); font-size: var(--size-caption); line-height: var(--leading-small); }
.contents.history .history-search:not([hidden]) ~ .history-list li.day:first-child h3 { margin-top: var(--space-3); }
.contents.history li + li { margin-top: var(--space-1); }
.contents.history li.day h3 { margin-top: var(--space-5); }
.contents.history li.day:first-child h3 { margin-top: 0; }
/* The row being read, and the message of it the reader went to, as the page you are on is drawn. */
.contents.history button[aria-current="true"] { background: var(--frame-hover); }
/* A row's own messages, the person's words, one line each, set in under their row. */
.contents.history .history-messages { margin: var(--space-1) 0 var(--space-2) var(--space-4); padding-left: var(--space-2); border-left: 1px solid var(--frame-line); }
/* A found line opens with whose words it holds, the person's or cx's, in the ink a title has; the words after it keep the line's own. */
.contents.history .history-messages .whose { color: var(--frame-ink); }
.contents.history .history-messages li + li { margin-top: 0; }
.contents.history .history-messages.alone { margin: 0; padding-left: 0; border-left: 0; }
.contents.history .history-messages button { padding: var(--space-1) var(--space-3); color: var(--frame-quiet); }
.contents.history .history-messages button:hover:not(:disabled), .contents.history .history-messages button[aria-current="true"] { color: var(--frame-ink); }
/* The words a search found: the action colour, strong, on its wash. Dark's action colour reads 4.42:1 on its wash, its hover 5.49:1. */
.contents.history mark { border-radius: var(--radius-small); background: var(--act-wash); color: var(--act); font-weight: var(--weight-strong); }
[data-theme="dark"] .contents.history mark { color: var(--act-hover); }
.contents.history .empty { margin: var(--space-2) 0 0; padding: 0 var(--space-3); color: var(--frame-quiet); }
.contents.history .empty .link { display: inline; width: auto; padding: 0; color: var(--frame-ink); text-decoration: underline; }
/* A title arriving settles in once, never bounces. */
.contents.history .arrived { animation: settle var(--motion-quick) var(--ease); }
@keyframes settle { from { opacity: 0; transform: translateY(var(--space-2)); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .contents.history .arrived { animation: none; } .item.revealed { transition: none; } }
/* The sources bought from most recently, under the Plugins entry: its sibling, so a row lights and opens alone. A row is its source's mark
   and name, and this month's figure in money's colour; a purchase sweeps over it and back, with a hairline riding the edge. */
.entries > .rows { display: flex; flex-direction: column; gap: var(--space-1); margin: var(--space-1) var(--space-3) var(--space-3); padding: 0; list-style: none; }
.rows .row { position: relative; display: block; height: 1.9rem; border-radius: var(--radius); overflow: hidden; font-size: var(--size-small); line-height: var(--leading-small); }
.rows .row:hover, .rows .row:focus-visible { background: var(--frame-hover); }
.rows .face { position: absolute; inset: 0; display: flex; align-items: center; gap: var(--space-4); padding: 0 var(--space-3); }
.rows .face.over { visibility: hidden; }
.rows .mark { flex: none; display: grid; place-items: center; width: 1.15rem; height: 1.15rem; border-radius: var(--radius-small); background: var(--frame-hover); border: 1px solid var(--frame-line); font-size: var(--size-caption); font-weight: var(--weight-strong); line-height: var(--leading-glyph); color: var(--frame-ink); }
.rows .name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rows .month { flex: none; font-size: var(--size-caption); }
.rows .face.over .name { font-family: var(--font-mono); font-size: var(--size-caption); font-variant-numeric: tabular-nums; }
.rows .face.over .month { color: var(--frame-ink); }
.rows .hair { position: absolute; left: 0; top: 24%; bottom: 24%; width: 1px; background: var(--frame-ink); opacity: 0; pointer-events: none; }
/* The receipt on its way from a row to cx: cx's own drawing, in client px over the whole window, never catching a click. */
.flight { position: fixed; left: 0; top: 0; width: 100vw; height: 100vh; z-index: 50; pointer-events: none; overflow: visible; color: var(--cx-line); display: none; }
.dot { flex: none; width: 0.5rem; height: 0.5rem; border-radius: var(--radius-round); border: 1px solid var(--quiet); }
.on > .dot { border-color: var(--ink); background: var(--ink); }
/* The corner is the account: one block, and its menu opening upward over the sidebar. */
.sidebar-foot { flex: none; position: relative; display: flex; flex-direction: column; gap: var(--space-3); padding-top: var(--space-4); border-top: 1px solid var(--frame-line); }
.account-button { display: flex; align-items: center; gap: var(--space-4); width: 100%; padding: var(--space-3); border: none; border-radius: var(--radius); background: none; text-align: left; }
.account-button:hover:not(:disabled), .account-button[aria-expanded="true"] { background: var(--frame-hover); }
.avatar { flex: none; display: grid; place-items: center; width: 2rem; height: 2rem; border-radius: var(--radius-round); background: var(--frame-ink); color: var(--frame); font-size: var(--size-small); font-weight: var(--weight-strong); line-height: var(--leading-small); }
.who { min-width: 0; display: flex; flex-direction: column; line-height: var(--leading-tight); }
.who .name { font-weight: var(--weight-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who .figure { font-size: var(--size-small); }
.who .frozen { color: var(--frame-quiet); }
/* Only a balance that could not be read is a failure; below the floor it is still the person's money. */
.account-button.failed .figure { color: var(--bad); }
/* A menu over the page: drawn by its outline. */
.account-menu { position: absolute; z-index: 5; left: 0; right: 0; bottom: calc(100% + var(--space-2)); display: flex; flex-direction: column; padding: var(--space-2); border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); box-shadow: var(--float-shadow); }
.account-menu .menu-email { margin: 0; padding: var(--space-3) var(--space-4) var(--space-4); border-bottom: 1px solid var(--line); margin-bottom: var(--space-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-menu [role="menuitem"] { display: flex; flex-direction: column; padding: var(--space-3) var(--space-4); border: none; border-radius: var(--radius); background: none; text-align: left; color: inherit; text-decoration: none; }
.account-menu [role="menuitem"]:hover, .account-menu [role="menuitem"]:focus-visible { background: var(--hover); }
:where([data-theme="dark"]) :is(.account-menu [role="menuitem"]:hover, .account-menu [role="menuitem"]:focus-visible) { background: var(--float-hover); }
.account-menu [role="menuitem"] .quiet { font-size: var(--size-caption); }
.sidebar-foot .marker { margin: 0; padding: 0 var(--space-3); font-size: var(--size-small); line-height: var(--leading-small); }
.bar { display: block; height: 0.3rem; margin: var(--space-2) 0 var(--space-1); border-radius: var(--radius-round); background: var(--wash); overflow: hidden; }
.bar > span { display: block; height: 100%; border-radius: var(--radius-round); background: var(--quiet); }
/* Credit spent is the person's own money. */
.credit .bar > span, .warned .bar > span { background: var(--money); }
.failed .bar > span { background: var(--bad); }
@media not (min-width: 56rem) {
  .sidebar { position: absolute; z-index: 4; top: 0; bottom: 0; left: 0; width: min(18rem, 86vw); border-right-color: var(--float-edge); box-shadow: var(--float-shadow); }
  .app.sidebar-shown .backdrop { display: block; position: absolute; z-index: 3; inset: 0; background: var(--scrim); }
}

main { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* The page keeps the reader's place itself when an earlier part arrives above it; the browser's own anchoring would move it twice. */
.scroller { flex: 1; min-height: 0; overflow-y: auto; overflow-anchor: none; mask-image: linear-gradient(to bottom, var(--ground) calc(100% - var(--space-9)), transparent); }
/* The browser makes the conversation's scroll a Tab stop of its own; its ring is drawn inside it, which reaches the window's edge. */
.scroller:focus-visible { outline-offset: -2px; }
/* Whatever the conversation brings into view stands clear of its edges by one room: a control's ring, drawn outside it, is whole, and
   a message, a day line or quoted words the page goes to land that far under the top. At the bottom the room is that much above the
   fade, which is as high as the conversation's own foot: a control under the newest message that takes the focus is drawn whole. */
.scroller { scroll-padding-block: var(--space-5) calc(var(--space-9) + var(--space-5)); }
.stream-waiting { text-align: center; }
.stream, .settings { width: 100%; max-width: 46rem; margin: 0 auto; padding: 0 var(--space-6); }
.bottom > * { width: calc(100% - 2 * var(--space-6)); max-width: 44rem; margin: 0 auto; }
/* The stream's foot is as tall as the scroller's fade, so at the end the last line stands whole above it. */
.stream { padding-top: var(--space-9); padding-bottom: var(--space-9); }
/*
 * The stream as pi draws a conversation, in the theme's names: the person's message in their bubble, the model's text with nothing
 * behind it, its thinking inline and whole under its label, and each step a quiet card on the wash, named in the page's words, its
 * command and output quieter than prose.
 */
.item { margin: 0 0 var(--space-5); }
/* One blank line between every piece, as pi's spacers give: a message, its thinking and text, each step. */
.item > :not(:last-child) { margin-bottom: var(--space-5); }
.item > :last-child { margin-bottom: 0; }
/* What hangs under a message, placed out of its flow, is not the next piece: the last piece in the flow ends the bubble with no gap. */
.item.user > :not(.actions, .held-next):not(:has(~ :not(.actions, .held-next))) { margin-bottom: 0; }
.item.user { width: fit-content; max-width: 75%; margin-left: auto; padding: var(--space-4) var(--space-5); border-radius: var(--radius-large); background: var(--wash); }
/* Each new message the person sends starts after a clear gap: their messages are where they find their way back. */
.item:not([hidden]) ~ .item.user { margin-top: var(--space-7); }
.stream-earlier:has(> .item:not([hidden])) ~ .item.user { margin-top: var(--space-7); }
/* The place a jump landed on is marked by a ground, for a moment, so the eye finds it: the ring is focus alone. */
.item.revealed { background: var(--act-wash); box-shadow: 0 0 0 var(--space-2) var(--act-wash); border-radius: var(--radius-small); transition: background var(--motion-quick) var(--ease), box-shadow var(--motion-quick) var(--ease); }
.item.user.revealed { border-radius: var(--radius-large); }
/* The day the person's messages under it were sent, once per day on the page, scrolling with the conversation. */
.stream .day-line { margin: var(--space-6) 0 var(--space-4); padding: var(--space-1) 0; color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); text-align: center; }
.stream-later { margin: var(--space-6) 0 0; text-align: center; }
/* Back to latest takes its own room under the conversation's view while it shows, so it never lies over the words it would hide. */
.latest-slot { flex: none; display: flex; justify-content: center; }
.latest-slot.showing { padding: var(--space-2) 0; }
.to-latest { display: flex; align-items: center; gap: var(--space-3); border-color: var(--float-edge); border-radius: var(--radius-round); background: var(--raised); box-shadow: var(--float-shadow); white-space: nowrap; }
.to-latest[hidden] { display: none; }
.item.user > .quiet { margin: var(--space-1) 0 0; }
/* Said under the bubble, not in it: the page's word about the message, not the person's. */
.item.user:has(> .held-next) { position: relative; margin-bottom: calc(var(--space-2) + 1em * var(--leading-small)); }
.item.user > .held-next { position: absolute; top: 100%; right: 0; margin: var(--space-1) 0 0; font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
.item.user .markdown { margin-bottom: 0; }
/* The words a quote returns to, marked for a moment as a selection is drawn. */
::highlight(quoted) { background: var(--act-wash); color: var(--ink); }
/* The row under a message: its time and what can be done with it. It takes its room always, so showing it moves nothing, and begins where the message ends, so the pointer passes to it unbroken. Its gap clears a focus ring, drawn 4px out, beside every control and the time. */
.actions { display: flex; align-items: center; gap: var(--space-4); padding-top: var(--space-1); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); opacity: 0; transition: opacity var(--motion-quick) var(--ease); }
.item > .actions { margin-bottom: 0; }
.item.assistant > .actions { margin-top: calc(-1 * var(--space-4)); }
.item.user:has(> .actions) { position: relative; margin-bottom: calc(var(--space-5) + 1rem + 2 * var(--space-2) + var(--space-1)); }
.item.user > .actions { position: absolute; top: 100%; right: 0; white-space: nowrap; }
.item.user:has(> .actions) > .held-next { top: calc(100% + 1rem + 2 * var(--space-2) + var(--space-1)); }
.actions button { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border: none; background: none; color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); }
.actions button:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
.item:hover > .actions, .actions:focus-within { opacity: 1; }
/* A message cx has not read is dim, as pi's terminal draws a queued one; what can still be done with it is always shown under it. */
.item.user.waiting { color: var(--quiet); }
/* A link in it is dim with the words round it, and its line under it still says it is one. */
.item.user.waiting a { color: inherit; }
.actions.wait-actions { opacity: 1; }
/* Its two controls do opposite things and are always shown: each is a square target at least as high as its row's line, and under a
   finger or on a narrow page a larger one, with the room under the message grown to hold it. */
.wait-actions button { justify-content: center; min-width: calc(1rem + 2 * var(--space-2)); min-height: calc(1rem + 2 * var(--space-2)); }
@media (pointer: coarse), not (min-width: 56rem) {
  .wait-actions button { min-width: var(--space-8); min-height: var(--space-8); }
  .item.user.waiting:has(> .actions) { margin-bottom: calc(var(--space-5) + var(--space-8) + var(--space-1)); }
}
/* A row's controls are marks alone. Each one's word stands over it while the pointer or the focus is on it, on the ground and outline
   of whatever lies over the page, and ends at the row's own edge, so a narrow page does not cut it. The time takes no press. */
.actions > button, .actions > .when { position: relative; }
.actions > .when { cursor: default; }
.tip { position: absolute; z-index: 2; bottom: calc(100% + var(--space-2)); display: none; width: max-content; max-width: min(20rem, 70vw); padding: var(--space-2) var(--space-4); border: 1px solid var(--float-edge); border-radius: var(--radius); background: var(--raised); box-shadow: var(--float-shadow); color: var(--ink); font-size: var(--size-caption); line-height: var(--leading-small); text-align: left; white-space: normal; pointer-events: none; }
.user-actions .tip, .wait-actions .tip { right: 0; }
.answer-actions .tip { left: 0; }
.actions > :hover > .tip, .actions > :focus-visible > .tip { display: block; }
.icon { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-reduced-motion: reduce) { .actions { transition: none; } }
/* Quote on a selection floats just above the selection's first line. */
.quote-pick { position: absolute; z-index: 3; display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-4); border-color: var(--float-edge); background: var(--raised); box-shadow: var(--float-shadow); white-space: nowrap; }
.quote-pick[hidden] { display: none; }
/* The quotes in the message box: a card each, side by side, scrolling sideways past the box's width; a hairline sets the row apart from the writing area. */
.quoted { margin: var(--space-1) 0 var(--space-2); padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.quoted[hidden] { display: none; }
/* A scrolling row clips both ways: the room above and below holds a remove control's ring whole. */
.quoted .cards { display: flex; gap: var(--space-3); overflow-x: auto; padding-block: var(--space-2); margin-block: calc(-1 * var(--space-2)) 0; }
.quoted .quote-card { flex: none; display: flex; align-items: flex-start; gap: var(--space-2); width: 12rem; padding: var(--space-3) var(--space-2) var(--space-3) var(--space-4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--ground); }
.quoted .quote-body { flex: 1; min-width: 0; padding-left: var(--space-3); border-left: 3px solid var(--edge); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.quoted .excerpt { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; color: var(--ink); }
.quoted .when { display: block; margin-top: var(--space-1); font-size: var(--size-caption); }
.quoted .remove { flex: none; display: inline-flex; align-items: center; justify-content: center; width: calc(1rem + 2 * var(--space-2)); height: calc(1rem + 2 * var(--space-2)); margin: calc(-1 * var(--space-2)) 0; padding: 0; border: none; background: none; color: var(--quiet); font-size: var(--size-lead); line-height: var(--leading-tight); }
.quoted .remove:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
:where([data-theme="dark"]) .quoted .remove:hover:not(:disabled) { background: var(--float-hover); }
/* Words for a screen reader alone. */
/* The quotes in a sent message: the same rule, up to two lines of each and when it was said; a press goes to where it was said. */
.item.user .quote-refs { display: flex; flex-direction: column; gap: var(--space-3); margin: 0 0 var(--space-3); }
.item.user .quote-ref { position: relative; display: block; width: 100%; padding: 0 0 0 calc(var(--space-4) + 3px); border: none; background: none; color: var(--quiet); text-align: left; font-size: var(--size-small); line-height: var(--leading-small); }
.item.user button.quote-ref:hover:not(:disabled) { background: none; color: var(--ink); }
/* The rule is drawn square beside the words, whatever the control's own corners are. */
.item.user .quote-ref::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--edge); }
.quote-ref .excerpt { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.quote-ref .when { display: block; font-size: var(--size-caption); }
.item.user .note { margin-bottom: var(--space-4); }
.markdown > :first-child { margin-top: 0; }
.markdown > :last-child { margin-bottom: 0; }
.markdown { overflow-wrap: anywhere; margin-bottom: var(--space-4); }
.markdown h1 { font-size: var(--size-title); }
.markdown h2 { font-size: var(--size-lead); }
.markdown h3, .markdown h4 { font-size: var(--size-body); }
.markdown h1, .markdown h2, .markdown h3, .markdown h4 { margin: var(--space-6) 0 var(--space-3); line-height: var(--leading-tight); }
.markdown table { border-collapse: collapse; display: block; overflow-x: auto; font-variant-numeric: tabular-nums; }
/* A cell keeps its words and figures whole, so 412 never reads 41/2: a table wider than the column scrolls sideways in its own box. */
.markdown th, .markdown td { padding: var(--space-2) var(--space-4); border: 1px solid var(--line); text-align: left; overflow-wrap: normal; word-break: normal; }
.markdown th { background: var(--wash); }
.markdown pre { padding: var(--space-4) var(--space-5); border-radius: var(--radius); background: var(--wash); }
.markdown code { padding: 0 var(--space-1); border-radius: var(--radius-small); background: var(--wash); }
.markdown pre code { padding: 0; background: none; }
.markdown blockquote { margin: var(--space-4) 0; padding-left: var(--space-5); border-left: 3px solid var(--line); color: var(--quiet); }
a.file { text-decoration-style: dotted; }
a.file::after { content: " ↓"; font-size: var(--size-caption); line-height: var(--leading-small); }
/* Thinking is the model's own voice: upright in every language, whole and never folded, in its own colour a step back from ink. Each run
   opens with its name, so what sets it apart from the answer is said in words and not by colour alone. */
.thinking { display: block; color: var(--thinking); }
.thinking-label { display: block; margin-bottom: var(--space-1); color: var(--quiet); font-size: var(--size-caption); font-weight: var(--weight-strong); line-height: var(--leading-small); }
.thinking .markdown { margin-bottom: 0; }
/* Where a message stopped: brick for an error, ink for a stop the person made, which is not a failure. */
.stop { color: var(--bad); }
.stop.stopped { color: var(--ink); }
.stop p { margin: 0; }
.tool, .note { padding: var(--space-4) var(--space-5); border-radius: var(--radius); }
.tool, .shell { font-size: var(--size-small); line-height: var(--leading-small); }
/* A step is a quiet card on the wash, finished or not; the running step is the one with an outline, and a failed step is on the error's wash. */
.tool { border: 1px solid var(--step-edge); background: var(--step); }
.tool.pending { border-color: var(--live-edge); background: var(--live-wash); }
.tool.error { border-color: var(--bad-wash); background: var(--bad-wash); }
.tool pre, .shell pre { font-family: var(--font-mono); font-size: var(--size-small); line-height: var(--leading-small); }
.tool .command, .shell .command, .tool .args { color: var(--quiet); }
.tool .head, .shell .head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-4); overflow-wrap: anywhere; }
.tool .setting { color: var(--quiet); }
/* The chat's own mark in a step's header: a word in a hairline, so no state rests on colour alone. Paid is money's; Failed is the error's. */
.tag { flex: none; padding: 0 var(--space-2); border: 1px solid var(--line); border-radius: var(--radius-small); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); }
.tag.failed { border-color: var(--bad-line); color: var(--bad); }
.tag.stopped { color: var(--ink); }
.stop.stopped { display: flex; }
.tool > :not(:first-child), .shell > :not(:first-child) { margin-top: var(--space-3); }
.tool .more, .shell .more { display: block; padding: 0; border: none; background: none; color: var(--quiet); font: inherit; text-align: left; }
.tool .more:hover:not(:disabled), .shell .more:hover:not(:disabled) { background: none; text-decoration: underline; }
.tool .timing, .shell .status-line { margin-bottom: 0; color: var(--live); }
/* A file's text on a step's card is the card's: at its size and in its quiet colour, no heading in it larger than the card's own words. */
.tool .written { color: var(--quiet); }
.tool .written .markdown { margin-bottom: 0; }
.tool .written h1, .tool .written h2, .tool .written h3, .tool .written h4 { font-size: inherit; }
.note { border: 1px solid var(--line); background: var(--raised); }
/* A dialog is what cx's work waits on: a lifted card with the running step's outline, answered where it stands. */
.stream-dialogs > * { margin: 0 0 var(--space-5); }
.dialog { padding: var(--space-5); border: 1px solid var(--live-edge); border-radius: var(--radius); background: var(--raised); }
.dialog > * { margin: 0; }
.dialog > * + *:not([hidden]) { margin-top: var(--space-4); }
.dialog-title { font-weight: var(--weight-strong); overflow-wrap: anywhere; }
.dialog-message { overflow-wrap: anywhere; white-space: pre-wrap; }
.dialog-controls { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; padding: 0; border: none; }
.dialog-options { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-2); }
.dialog-options button { text-align: left; overflow-wrap: anywhere; }
.dialog-acts { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.dialog input, .dialog textarea { width: 100%; padding: var(--space-3) var(--space-4); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--ground); font-size: var(--size-body); line-height: var(--leading-body); }
.dialog textarea { resize: vertical; font-family: var(--font-mono); font-size: var(--size-small); line-height: var(--leading-small); }
.dialog-unsent { color: var(--bad); }
/* A package's word in passing: it stands long enough to read, then goes. */
.dialog-notice { color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); overflow-wrap: anywhere; animation: notice-goes linear forwards; }
.dialog-notice.error { color: var(--bad); }
@keyframes notice-goes { 0%, 92% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .dialog-notice { animation: none; } }
.note-head, .note-head:hover:not(:disabled) { display: block; width: 100%; padding: 0; border: none; background: none; font-size: inherit; line-height: inherit; text-align: left; }
.note-head:hover { text-decoration: underline; }
.note .markdown { display: block; margin: var(--space-4) 0 0; }
.shell { padding: var(--space-3) 0; border-block: 1px solid var(--line); }
/* A warning is not a failure: Stopped, a stop the person made, is said in ink. */
.t-warning, .t-added { color: var(--ink); }
.t-output, .t-muted, .t-context, .t-removed { color: var(--quiet); }
.t-error { color: var(--bad); }
/* A word a step changed: the page's mark, whichever way it changed, in ink; a removed word is struck through, so the change is not colour alone. */
mark { border-radius: var(--radius-small); background: var(--mark); color: var(--ink); }
mark.t-removed { color: var(--ink); text-decoration: line-through; }
.fold { margin-top: var(--space-2); padding: 0; border: none; background: none; color: var(--act); font-size: var(--size-small); line-height: var(--leading-small); text-decoration: underline; }
.marker { margin: var(--space-3) 0 0; font-size: var(--size-small); line-height: var(--leading-small); }
.marker.failed { padding: var(--space-4) var(--space-5); border: 1px solid var(--bad-line); border-radius: var(--radius); color: var(--bad); }
/* A warning is said in ink; on the balance it is about the person's own money. */
.marker.warned { color: var(--ink); }
.settings .marker.warned { color: var(--money); }

.bottom { position: relative; flex: none; padding: var(--space-2) 0 var(--space-4); background: var(--ground); }
/* The status line: cx above the composer at its left edge, then what the page has to say, coloured by what it says. A line that says
   something failed and may need the person to act is brick; the low balance is money's; every other line is quiet, a wait included. */
/* It stands over the conversation's faded foot rather than on a row of its own: nobody reads there, and the conversation keeps the room.
   The row lets a scroll through to the conversation; cx and its computer still take a click. */
.status { position: absolute; bottom: 100%; left: 0; right: 0; display: flex; align-items: flex-end; gap: var(--space-4); min-height: 1.3rem; margin: 0 auto var(--space-1) !important; color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); pointer-events: none; }
.status :is(a, button, svg) { pointer-events: auto; }
/* cx at its computer: every colour it draws is the theme's `--cx-*`. */
.cx-slot { flex: none; width: 5.8rem; height: 2rem; display: flex; align-items: flex-end; justify-content: flex-start; color: var(--cx-line); }
.cx-slot svg { display: block; margin-bottom: calc(-1 * var(--space-1)); }
.cx-slot svg .cx-target:focus { outline: none; }
/* A pointer's target is never under 24 px: the drawing's own boxes are kept, and an unseen edge around each takes the press. */
.cx-slot svg .cx-target { stroke: transparent; stroke-width: 6px; vector-effect: non-scaling-stroke; }
/* The ring is the target's own edge, which keeps its width on the screen whatever the drawing's scale: an outline is drawn in the
   drawing's units and comes out a hairline. */
.cx-slot svg .cx-target:focus-visible { stroke: var(--act); stroke-width: 2px; }
.status-text { padding-bottom: var(--space-2); }
/* Words over the faded foot stand on the page's ground, edged soft into the fade, so a conversation scrolled under them never shows
   through them. */
.status-text:not(:empty) { background: var(--ground); border-radius: var(--radius); box-shadow: 0 0 var(--space-3) var(--space-2) var(--ground); }
.status.held .status-text { color: var(--bad); }
/* What cx says, at its upper left: over the page, so drawn by its outline, with a small tail down toward cx's head. */
.cx-place { position: relative; flex: none; }
.cx-bubble { position: absolute; left: calc(-1 * var(--space-2)); bottom: calc(100% + var(--space-2)); z-index: 5; padding: var(--space-1) var(--space-4); border: 1px solid var(--float-edge); border-radius: var(--radius-large) var(--radius-large) var(--radius-large) var(--radius-small); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; box-shadow: var(--float-shadow); pointer-events: none; }
.cx-bubble::after { content: ""; position: absolute; left: var(--space-4); bottom: calc(-1 * var(--space-2) - 1px); width: var(--space-4); height: var(--space-4); transform: rotate(45deg) scale(0.75); background: var(--raised); border-right: 1px solid var(--float-edge); border-bottom: 1px solid var(--float-edge); }
/* Out of sight, never out of the tree: a live region shown in the same step its words arrive is often not spoken. */
.cx-bubble.quiet, .cx-place.open .cx-bubble, .cx-place.tipped .cx-bubble { width: 1px; height: 1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; box-shadow: none; }
.cx-bubble.quiet::after, .cx-place.open .cx-bubble::after, .cx-place.tipped .cx-bubble::after { content: none; }
.cx-bubble .money { font-size: inherit; }
/* What a click on cx or on its computer opens: one card for both, over the page, placed by the page against the one that was clicked,
   so it reaches cx beside the answer too. One line says what that one is doing now; under a rule, what can be done now. */
.cx-card { position: fixed; z-index: 5; left: 0; top: 0; display: none; flex-direction: column; min-width: 12rem; max-width: min(20rem, calc(100vw - 2 * var(--space-4))); padding: var(--space-2); border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); box-shadow: var(--float-shadow); pointer-events: auto; }
.cx-place.open .cx-card { display: flex; }
.cx-answer-title { margin: 0; padding: var(--space-3) var(--space-4); font-weight: var(--weight-strong); }
.cx-answer-acts { display: flex; flex-direction: column; margin-top: var(--space-1); padding-top: var(--space-2); border-top: 1px solid var(--line); }
/* A card with nothing to do ends at its words. */
.cx-answer-acts:empty { display: none; }
.cx-answer-acts :is(button, a) { padding: var(--space-3) var(--space-4); border: none; border-radius: var(--radius); background: none; color: var(--ink); font: inherit; text-align: left; text-decoration: none; cursor: pointer; }
.cx-answer-acts :is(button, a):hover { background: var(--wash); }
.cx-answer-acts a[data-act="help"] { display: flex; flex-direction: column; align-items: flex-start; }
.cx-answer-acts a[data-act="help"] .quiet { color: var(--quiet); font-size: var(--size-caption); }
/* A ring drawn inside its row, so the card's edge never meets it. */
.cx-answer-acts :is(button, a):focus-visible { outline-offset: -2px; }
/* A finger's row on a narrow window or a touch screen. */
@media (pointer: coarse), not (min-width: 30rem) {
  .cx-answer-acts :is(button, a) { display: flex; align-items: center; min-height: 2.75rem; }
}
/* What hovering a target says: its card's title where the card would open, with no tail, since cx is not the one speaking. */
.cx-tip { position: fixed; z-index: 5; left: 0; top: 0; padding: var(--space-1) var(--space-4); border: 1px solid var(--float-edge); border-radius: var(--radius); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; box-shadow: var(--float-shadow); pointer-events: none; }
.cx-tip[hidden] { display: none; }
/* Out of reach with the computer last heard on: the no-signal mark, laid over the drawing's corner. */
.cx-nosignal { position: absolute; z-index: 2; left: 0; top: 0; display: grid; place-items: center; width: 1rem; height: 1rem; border: 1px solid var(--float-edge); border-radius: var(--radius-round); background: var(--raised); color: var(--ink); pointer-events: none; }
.cx-nosignal[hidden] { display: none; }
.cx-nosignal svg { width: 0.75rem; height: 0.75rem; }
.cx-nosignal-cross { stroke: var(--bad); }
.composer { display: flex; flex-direction: column; border: 1px solid var(--edge); border-radius: var(--radius-large); background: var(--raised); padding: var(--space-3) var(--space-4) var(--space-3) var(--space-5) !important; box-shadow: var(--float-shadow); }
.composer:focus-within { border-color: var(--act); }
.composer textarea { min-height: 2.8rem; max-height: 40vh; padding: var(--space-2) 0; border: none; outline: none; resize: none; background: none; color: var(--ink); field-sizing: content; }
.composer textarea::placeholder { color: var(--quiet); opacity: 1; }
/* The / list lies over the page above the box, as wide as it, drawn as the model card is; the line under the arrows or the pointer is
   shaded, one shade for both. Open, it hides cx's line above the box whole, so no edge of cx's desk shows under it. Past seven lines
   it scrolls. */
.composer { position: relative; }
.slash { position: absolute; z-index: 6; left: -1px; right: -1px; bottom: calc(100% + var(--space-3)); display: flex; flex-direction: column; max-height: calc(7 * var(--row) + 2 * var(--space-2) + 2px); overflow-y: auto; padding: var(--space-2); border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); box-shadow: var(--float-shadow); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.slash[hidden] { display: none; }
.bottom:has(.slash:not([hidden])) .status { visibility: hidden; }
.slash-row { flex: none; display: flex; align-items: center; gap: var(--space-5); min-width: 0; height: var(--row); padding: 0 var(--space-4); border-radius: var(--radius); cursor: pointer; }
.slash-row[aria-selected="true"] { background: var(--float-hover); }
.slash-name { flex: 0 1 auto; min-width: 0; overflow: hidden; font-weight: var(--weight-strong); white-space: nowrap; text-overflow: ellipsis; }
.slash-about { flex: 1; min-width: 0; color: var(--quiet); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.slash-said { margin: 0; padding: 0 var(--space-4); color: var(--quiet); line-height: var(--row); }
/* A closed message box: its reason where the words would be typed, as high as the field it stands for, and the one link the reason
   may hold. The link takes a press over 24 px each way by an unseen edge of its own, a finger's row on a narrow page or a touch screen. */
.composer-closed { min-height: 2.8rem; margin: 0; padding: var(--space-2) 0; color: var(--ink); }
.composer-closed a { position: relative; }
.composer-closed a::after { content: ""; position: absolute; inset: calc(-1 * var(--space-2)) 0; min-width: 1.5rem; }
@media (pointer: coarse), not (min-width: 30rem) {
  .composer-closed a::after { top: 50%; bottom: auto; height: 2.75rem; transform: translateY(-50%); }
}
.composer-row { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-4); }
/* The message box's one control: a mark and no word in a square of the theme's control radius, as high as a button that carries a word, so the box is as high as it
   was with two of those; it stands inside the box's padding, where its focus ring is drawn whole. Off with the focus still on it, it
   is drawn as any button that is off. */
.composer .control { flex: none; display: inline-flex; align-items: center; justify-content: center; width: calc(var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px); height: calc(var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px); padding: 0; border-radius: var(--radius); }
/* Under a finger or on a narrow page it is as large a target as a waiting message's controls, and takes from the box's padding what
   it grows by: the box stays as high. */
@media (pointer: coarse), not (min-width: 56rem) {
  .composer .control { width: var(--space-8); height: var(--space-8); margin-block: calc((var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px - var(--space-8)) / 2); }
}
/* As Stop its outline turns to ink under the pointer: the step from the raised ground to the hover ground cannot be seen in dark.
   Its mark is ink at rest, so the one live control does not read as off. */
.composer .control[data-does="stop"]:hover:not(:disabled) { border-color: var(--ink); }
.composer .control[aria-disabled="true"], .composer .control[aria-disabled="true"]:hover { border-color: var(--line); background: var(--wash); color: var(--quiet); cursor: default; }
/* The files in the message box and on a sent message. */
/* ---- Adding ---- */

/* The control that adds files: a mark alone at the row's left, as high as the box's one control. It has no outline, as the quote card's
   remove has none: the box's one outlined control is the one that sends. Its mark lines up with the words typed above it. Under a
   finger or on a narrow page it grows as that control does. */
.composer-row .add { flex: none; display: inline-flex; align-items: center; justify-content: center; width: calc(var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px); height: calc(var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px); margin-left: calc(-1 * var(--space-3)); margin-right: auto; padding: 0; border: none; border-radius: var(--radius); background: none; color: var(--quiet); }
.composer-row .add:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
@media (pointer: coarse), not (min-width: 56rem) {
  .composer-row .add { width: var(--space-8); height: var(--space-8); margin-block: calc((var(--size-small) * var(--leading-small) + 2 * var(--space-2) + 2px - var(--space-8)) / 2); }
}

/* Files dragged over the conversation: the box they will join says so, its outline broken in the colour of what is acted on, and its
   words over everything it holds until the files are dropped or leave. */
.composer { position: relative; }
.composer.dropping, .composer.dropping:focus-within { border-style: dashed; border-color: var(--act); }
.drop-said { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; margin: 0; padding: 0 var(--space-6); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); text-align: center; pointer-events: none; }
.drop-said[hidden] { display: none; }

/* ---- Ready to send ---- */

/* Every card in the row is one height, a quote's or a file's, whatever it holds, so the box keeps its height while files go up, fail
   or finish (Jack, 2026-10-19: 「我觉得组建的卡片高度要一致，不然会拉伸聊天框」). Two lines of words stand at the top, and one line in the
   caption's size at the foot: a quote's time, or what a file's card has to say. A quote's words run to two lines, as the sent message's
   quote does. */
.quoted .quote-card { height: calc(2 * var(--size-small) * var(--leading-small) + var(--space-1) + var(--size-caption) * var(--leading-small) + 2 * var(--space-3) + 2px); }
.quoted .quote-body { align-self: stretch; display: flex; flex-direction: column; }
.quoted .quote-body .excerpt { -webkit-line-clamp: 2; }
.quoted .quote-body .when { margin-top: auto; }

/* A file's card: its picture, or one mark for every kind, as tall as the two lines of its name beside it; then its name as it stands in
   the seller's files, and at the foot what the card has to say or, with nothing to say, the file's size. A name breaks as main's quoted
   words do, between Chinese characters and at the end of a word, and inside a word only when it is wider than the card, and runs to two
   lines, then an ellipsis. × stands where the quote card's does, and the foot runs on under it, on one line. A card that cannot go has
   the error's outline and says why in the error's colour; a file still going up says so in the words of work under way. Try again is a
   mark at the card's lower right, its word on hover, as the conversation's row controls are. */
.quoted .file-card { position: relative; gap: var(--space-4); padding-right: var(--space-4); }
.quoted .file-card .remove, .quoted .file-card .retry { position: absolute; right: var(--space-2); margin: 0; }
.quoted .file-card .remove { top: calc(var(--space-3) - var(--space-2)); }
.quoted .file-card .retry { bottom: calc(var(--space-3) - var(--space-2)); display: inline-flex; align-items: center; justify-content: center; width: calc(1rem + 2 * var(--space-2)); height: calc(1rem + 2 * var(--space-2)); padding: 0; border: none; background: none; color: var(--quiet); }
.quoted .file-card .retry:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
.file-thumb { flex: none; display: grid; place-items: center; width: calc(2 * var(--size-small) * var(--leading-small)); height: calc(2 * var(--size-small) * var(--leading-small)); overflow: hidden; border-radius: var(--radius-small); background: var(--wash); color: var(--quiet); }
.file-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* The name keeps clear of ×: the room × takes from the card's right edge, less the card's own, and the gap a quote card leaves. */
.file-body { flex: 1; align-self: stretch; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); padding-right: calc(1rem + 4 * var(--space-2) - var(--space-4)); font-size: var(--size-small); line-height: var(--leading-small); }
.file-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; color: var(--ink); }
.file-said { max-width: calc(100% + (1rem + 4 * var(--space-2) - var(--space-4))); margin: auto calc(-1 * (1rem + 4 * var(--space-2) - var(--space-4))) 0 0; overflow: hidden; color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); white-space: nowrap; text-overflow: ellipsis; }
.file-card.uploading .file-said { color: var(--live); }
.quoted .file-card.large, .quoted .file-card.failed { border-color: var(--bad-line); }
.file-card.large .file-said, .file-card.failed .file-said { color: var(--bad); }
/* A failed card's foot keeps clear of Try again, as its name does of ×. */
.file-card.failed .file-said { max-width: 100%; margin-right: 0; }

/* ---- Sent ---- */

/* The files a message names, over its words: each a card with its name, on the ground the message box's cards had. A waiting message
   is dim, its files with it. */
.item.user .file-refs { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: 0 0 var(--space-4); }
.item.user .file-refs:last-child { margin-bottom: 0; }
.file-ref { display: inline-flex; align-items: center; gap: var(--space-3); max-width: 100%; padding: var(--space-2) var(--space-4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.file-ref .icon { flex: none; color: var(--quiet); }
.file-ref-name { min-width: 0; overflow-wrap: anywhere; }
.item.user.waiting .file-ref { color: inherit; }
.icon .solid { fill: currentColor; }
/* The model card under the composer's right edge: one quiet line closed, seven rows of one height open, upward over the composer. */
.model-line { margin-top: var(--space-1) !important; }
.pick-said { margin: 0; padding: 0 var(--space-3); color: var(--bad); font-size: var(--size-small); line-height: var(--leading-small); text-align: right; }
/* The line holds the height its model will take, so nothing moves when a read fills it. */
.mp { position: relative; display: flex; justify-content: flex-end; min-height: calc(1em * var(--leading-small) + 2 * var(--space-1)); font-size: var(--size-small); line-height: var(--leading-small); }
.mp-trigger { max-width: 100%; padding: var(--space-1) var(--space-3); border: none; border-radius: var(--radius); background: none; color: var(--quiet); font: inherit; font-size: inherit; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-trigger:hover, .mp-trigger[aria-expanded="true"] { background: var(--hover); color: var(--ink); }
:where([data-theme="dark"]) :is(.mp-trigger:hover, .mp-trigger[aria-expanded="true"]) { background: var(--float-hover); }
.mp-trigger.mp-unserved { color: var(--bad); }
/* With no model on offer a control that chooses nothing is not drawn: the line is the model in use in plain words. */
.model-label { min-width: 0; padding: var(--space-1) var(--space-3); color: var(--quiet); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Where the line does not fit, the vendor's name gives way, to an ellipsis, and the model's keeps its length, cut only where it alone is
   longer than the line less the vendor's first letter and the dot. */
:is(.mp-trigger, .model-label):has(> .mp-model) { display: inline-flex; align-items: baseline; }
.mp-vendor { flex: 0 1 auto; min-width: 1.5em; overflow: hidden; text-overflow: ellipsis; }
.mp-sep { flex: none; white-space: pre; }
.mp-model { flex: none; max-width: calc(100% - 2.5em); overflow: hidden; text-overflow: ellipsis; }
/* A menu over the page, drawn by its outline; wide enough for a model name beside the tag that says who pays, on a vendor reached more
   than one way. */
.mp-card { position: absolute; z-index: 6; right: 0; bottom: calc(100% + var(--space-3)); width: 24rem; max-width: 100%; display: flex; flex-direction: column; padding: var(--space-2); border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); box-shadow: var(--float-shadow); opacity: 0; visibility: hidden; transform: translateY(var(--space-3)); pointer-events: none; transition: opacity var(--motion-quick) var(--ease), transform var(--motion-quick) var(--ease), visibility 0s linear var(--motion-quick); }
.mp.open .mp-card { opacity: 1; visibility: visible; transform: none; pointer-events: auto; transition-delay: 0s; }
/* The card sets its rows from its own row count; the stylesheet holds only each row's height. */
.mp-rows { display: grid; }
.mp-row { display: flex; align-items: center; gap: var(--space-4); min-width: 0; height: var(--row); margin: 0; padding: 0 var(--space-4); border: none; border-radius: var(--radius); background: none; color: inherit; font: inherit; font-size: inherit; text-align: left; cursor: pointer; }
.mp-row:hover, .mp-row:focus-visible { background: var(--hover); }
:where([data-theme="dark"]) :is(.mp-row:hover, .mp-row:focus-visible) { background: var(--float-hover); }
.mp-row:focus-visible { outline: 2px solid var(--act); outline-offset: -2px; }
.mp-empty { cursor: default; }
.mp-empty:hover { background: none; }
.mp-slot { flex: none; width: 1.3rem; display: grid; place-items: center; color: var(--quiet); }
.mp-glyph { width: 1.25rem; height: 1.25rem; color: var(--ink); }
.mp-tick { color: var(--ink); font-weight: var(--weight-strong); }
.mp-name { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.mp-in-use .mp-name, .mp-title .mp-name { font-weight: var(--weight-strong); }
.mp-tag { flex: none; padding: 0 var(--space-2); border: 1px solid var(--line); border-radius: var(--radius-small); color: var(--quiet); font-size: var(--size-caption); font-weight: var(--weight-regular); line-height: var(--leading-small); }
.mp-hint { flex: none; color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* On a vendor's level the version beside a series' name gives way first, so a narrow card keeps the series' name whole where the row has
   room for it; on the vendors' level Default keeps its name and the line beside it gives way first. */
.mp-name:has(> .mp-member) > .mp-text { flex: none; max-width: 100%; }
.mp-name > .mp-member { flex: 0 1 auto; min-width: 0; }
.mp-row > .mp-name:has(+ .mp-hint) { flex: 1 0 auto; }
.mp-row > .mp-name + .mp-hint { flex: 0 1 auto; min-width: 0; }
.mp-more { flex: none; color: var(--quiet); }
.mp-spacer { visibility: hidden; }
.mp-bars, .mp-cols { flex: none; display: flex; gap: var(--space-4); }
.mp-bar { display: block; width: 3rem; height: 0.32rem; border-radius: var(--radius-round); background: var(--wash); overflow: hidden; }
.mp-bar > span { display: block; height: 100%; border-radius: var(--radius-round); background: var(--quiet); }
.mp-bar.mp-bar-none { visibility: hidden; }
.mp-capability > span { background: var(--ink); }
/* Cost per task is a price: money's colour, which nothing else on the card has. */
.mp-cost > span { background: var(--money); }
.mp-cols span { width: 3rem; color: var(--quiet); font-size: var(--size-caption); font-weight: var(--weight-regular); line-height: var(--leading-small); text-align: center; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .mp-card { transition: none; } }
@media not (min-width: 56rem) { .mp-card { left: 0; right: 0; width: auto; } }
.signed-out { margin: var(--space-9) auto; text-align: center; }

/* One scroller, the page's: the column keeps its width, and the bar stands at the window's right edge. */
.settings { padding-top: var(--space-9); padding-bottom: var(--space-9); max-width: 46rem; }
main:has(> .settings) { overflow-y: auto; }
/* The models page scrolls with main alone, as the Plugins page does: one scroller, its bar at the window's edge, not the column's. */
.settings.plugins { overflow-y: visible; }
.settings .back { margin: 0 0 var(--space-4); font-size: var(--size-small); line-height: var(--leading-small); }
.credit { max-width: 22rem; }
.where { margin-top: var(--space-6); }
.where table { width: 100%; max-width: 30rem; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.where th { padding: var(--space-1) var(--space-6) var(--space-1) 0; font-weight: var(--weight-regular); text-align: left; white-space: nowrap; }
.where .amount { padding-right: var(--space-6); text-align: right; white-space: nowrap; }
.where .share { width: 60%; }
.settings h1 { margin: 0 0 var(--space-6); font-size: var(--size-display); line-height: var(--leading-tight); }
.settings h2 { margin: 0 0 var(--space-2); font-size: var(--size-lead); }
.settings h3 { margin: var(--space-6) 0 var(--space-1); font-size: var(--size-body); }
.settings section { margin-bottom: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--line); }
.settings p { margin: var(--space-2) 0; }
/* Every amount of the person's own money, a balance, a figure spent or a price, has one look: the system monospace, figures of one width,
   in money's colour; in the sidebar, the frame's money. */
.money { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--money); }
.sidebar .money { color: var(--frame-money); }
.figure { font-size: var(--size-title); }
.terms { margin: var(--space-1) 0; padding-left: var(--space-6); }
.source button { margin-top: var(--space-3); }
/* A state is a tag, as the board draws Off: a word in a hairline, not a control, so never forest. On is said by its filled dot. */
.state { display: inline-flex; align-items: center; gap: var(--space-2); flex: none; padding: 0 var(--space-2); border: 1px solid var(--line); border-radius: var(--radius-small); font-size: var(--size-caption); font-weight: var(--weight-regular); line-height: var(--leading-small); color: var(--quiet); white-space: nowrap; }
.state.on { color: var(--ink); }
.tile { flex: none; display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--radius); background: var(--wash); border: 1px solid var(--line); font-size: var(--size-small); font-weight: var(--weight-strong); line-height: var(--leading-small); color: var(--ink); }
.page-head { justify-content: space-between; margin-bottom: var(--space-3); }
.page-head h1 { margin: 0; }
a.button { padding: var(--space-2) var(--space-5); border: 1px solid var(--edge); border-radius: var(--radius); color: inherit; font-size: var(--size-small); line-height: var(--leading-small); text-decoration: none; }
a.button:hover, a.button:focus-visible { background: var(--hover); }
.count { margin-left: var(--space-3); font-size: var(--size-small); font-weight: var(--weight-regular); line-height: var(--leading-small); color: var(--quiet); }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: var(--space-5); margin-top: var(--space-5); }
.card { display: flex; flex-direction: column; gap: var(--space-4); min-height: 8.2rem; padding: var(--space-5) var(--space-6); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--raised); color: inherit; text-decoration: none; transition: border-color var(--motion-quick) var(--ease); }
.card:hover, .card:focus-visible { border-color: var(--edge); }
.card.missing { background: var(--wash); }
.card.missing .about { color: var(--quiet); }
.card.missing { border-style: dashed; }
.card.missing .tile { background: var(--ground); }
.card .row { flex-wrap: nowrap; gap: var(--space-4); }
.card .row { align-items: flex-start; }
.card .row strong { flex: 1; min-width: 0; padding-top: var(--space-1); overflow-wrap: anywhere; line-height: var(--leading-tight); }
.card .about { font-size: var(--size-small); line-height: var(--leading-small); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card .quiet { margin-top: auto; padding-top: var(--space-4); border-top: 1px solid var(--line); }
.plugin-head { gap: var(--space-4); }
.plugin-head h1 { margin: 0; }
.plugins section { margin-top: var(--space-6); }
.plugin-head .state { margin-left: auto; }
.ways { display: flex; flex-direction: column; margin-top: var(--space-4); border: 1px solid var(--line); border-radius: var(--radius-large); }
.way { display: flex; align-items: center; gap: var(--space-5); padding: var(--space-5) var(--space-6); color: inherit; text-decoration: none; }
.way + .way { border-top: 1px solid var(--line); }
.way:hover, .way:focus-visible { background: var(--hover); }
.way > span:first-child { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.seek { width: 100%; margin-top: var(--space-5); padding: var(--space-4) var(--space-5); }
/* A sign-in is one card under its row on the vendor's Settings, the questions' card with its field and presses laid out as theirs are, a row's room in from the list's edges and as wide as the page's sentences. Its code is read at a glance and copied whole. */
.sign-in .dialog-acts { align-items: center; }
.sign-in input::placeholder { color: var(--quiet); opacity: 1; }
.dialog-line { font-size: var(--size-small); line-height: var(--leading-small); color: var(--quiet); }
.dialog-line.failed { color: var(--bad); }
.dialog-code { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-5); }
.dialog-code code { font-family: var(--font-mono); font-size: var(--size-title); line-height: var(--leading-tight); user-select: all; }
.dialog a.button { display: inline-block; overflow-wrap: anywhere; }
.dialog p { overflow-wrap: anywhere; }
.pl-way-list .sign-in { max-width: calc(38rem + 2 * var(--space-5) + 2px); margin: 0 var(--space-5) var(--space-5); }
.pl-way-list .sign-in > p { max-width: none; margin-bottom: 0; }
.pl-page .dialog a.button { border-color: var(--line); background: var(--hover); }
.pl-page .dialog a.button:hover { border-color: var(--edge); background: var(--wash); }
/* A sign-in's last word stands under its row a row's room in; the flow's own words, quoted, take a line of their own under it. */
.pl-way-list .pl-last { max-width: none; margin: 0 var(--space-5) var(--space-5); overflow-wrap: anywhere; }
.pl-last .pl-last-words { display: block; flex-basis: 100%; }
/* A dialog over the page it stops: drawn by its outline, the page under it still seen through the scrim. */
dialog.confirm { max-width: 30rem; padding: var(--space-6) var(--space-7); border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); box-shadow: var(--float-shadow); }
dialog.confirm::backdrop { background: var(--scrim); }
dialog.confirm h2 { margin-top: 0; font-size: var(--size-lead); }

/* The Plugins page drawn from the catalogue. The page scrolls in main, so the bar sits at the window's right edge. */
main:has(> .pl-page) { overflow-y: auto; scroll-padding-block: var(--space-3); }
.pl-page { width: 100%; max-width: 72rem; margin: 0 auto; padding: var(--space-9) var(--space-7); }
@media not (min-width: 48rem) { .pl-page { padding-left: var(--space-6); padding-right: var(--space-6); } }
.pl-page h1 { margin: 0 0 var(--space-6); font-size: var(--size-display); line-height: var(--leading-tight); }
.pl-page .back { margin: 0 0 var(--space-4); font-size: var(--size-small); line-height: var(--leading-small); }
/* Show all's heading stands a heading's two steps under its back link. */
.pl-body > .back { margin-bottom: var(--space-6); }
.pl-page .back a { color: var(--quiet); text-decoration: none; }
.pl-page .back a:hover { color: var(--ink); }
.pl-icon { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.pl-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-5); margin-bottom: var(--space-6); }
.pl-views { display: flex; padding: var(--space-1); border: 1px solid var(--line); border-radius: var(--radius); background: var(--hover); }
.pl-view { padding: var(--space-2) var(--space-5); border-radius: var(--radius); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); text-decoration: none; }
.pl-view[aria-selected="true"] { background: var(--wash); color: var(--ink); font-weight: var(--weight-strong); }
.pl-sep { width: 1px; height: 1.25rem; background: var(--line); }
.pl-filters { display: flex; gap: var(--space-1); }
.pl-filter { padding: var(--space-2) var(--space-4); border-radius: var(--radius); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); text-decoration: none; }
/* A view or a filter that is not the one shown answers the pointer in its words. */
.pl-filter:hover, .pl-view:hover { color: var(--ink); }
.pl-filter[aria-current="true"] { background: var(--wash); color: var(--ink); }
.pl-tools { display: flex; align-items: stretch; gap: var(--space-4); margin-left: auto; }
.pl-searchbox:focus-within { outline: 2px solid var(--act); outline-offset: 2px; }
.pl-searchbox { display: flex; align-items: center; gap: var(--space-3); width: 15rem; padding: var(--space-2) var(--space-4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--hover); color: var(--quiet); }
.pl-search { flex: 1; min-width: 0; padding: 0; border: none; background: none; outline: none; font-size: var(--size-body); line-height: var(--leading-body); color: var(--ink); appearance: none; }
.pl-search::placeholder { color: var(--quiet); opacity: 1; }
.pl-search::-webkit-search-cancel-button { appearance: none; width: 0.65rem; height: 0.65rem; background: var(--ink); clip-path: polygon(15% 0, 50% 35%, 85% 0, 100% 15%, 65% 50%, 100% 85%, 85% 100%, 50% 65%, 15% 100%, 0 85%, 35% 50%, 0 15%); cursor: pointer; }
/* Create keeps its word on one line; on a narrow window the search box is what gives way. */
.pl-tools > .pl-menu { flex: none; display: flex; }
.pl-create { display: inline-flex; align-items: center; gap: var(--space-3); white-space: nowrap; }
.pl-menu-list.pl-create-list { min-width: 14rem; white-space: nowrap; }
.pl-menu-list.pl-create-list[hidden] { display: none; }
.pl-create-item { display: flex; align-items: center; gap: var(--space-4); width: 100%; padding: var(--space-3) var(--space-4); border-radius: var(--radius-small); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-create-item .pl-icon { flex: none; }
/* A row of a menu under the pointer takes the ground cut from the menu's own as the sidebar's is cut from the frame: the wash is a step the eye barely tells from the menu. A row that cannot be pressed does not answer. */
.pl-create-item:hover:not(:disabled), .pl-menu-list .pl-remove:hover:not(:disabled) { background: var(--float-hover); }
.pl-banner { display: flex; align-items: center; gap: var(--space-7); margin-bottom: var(--space-7); padding: var(--space-6) var(--space-7); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--wash); }
.pl-banner-text { flex: 1; min-width: 0; }
.pl-banner-text h2 { margin: 0 0 var(--space-2); font-size: var(--size-title); line-height: var(--leading-tight); }
.pl-banner-text p { margin: 0 0 var(--space-4); }
.pl-banner-text > .quiet { margin-bottom: var(--space-1); }
.pl-banner-text .row { display: flex; align-items: center; gap: var(--space-5); margin: var(--space-5) 0 0; }
.pl-banner-tiles { flex: none; display: flex; gap: var(--space-4); }
.pl-banner-art { flex: none; width: 13rem; margin: calc(-1 * var(--space-3)) var(--space-3) calc(-1 * var(--space-3)) 0; color: var(--ink); }
.pl-banner-art svg { display: block; width: 100%; height: auto; }
.pl-banner-art .pl-art-lens, .pl-banner-art .pl-art-fill { fill: var(--raised); }
/* One seven-second loop. Each part's own style is its last frame, so where motion is not wanted the drawing stands whole. */
.pl-banner-art * { animation-duration: 7s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; transform-box: fill-box; }
.pl-art-play { animation-name: pl-art-play; }
.pl-art-tag { animation-name: pl-art-tag; }
.pl-art-line { stroke-dasharray: 1; animation-name: pl-art-line; }
.pl-art-dot { transform-origin: center; }
.pl-art-dot.pl-art-0 { animation-name: pl-art-dot-0; } .pl-art-dot.pl-art-1 { animation-name: pl-art-dot-1; } .pl-art-dot.pl-art-2 { animation-name: pl-art-dot-2; } .pl-art-dot.pl-art-3 { animation-name: pl-art-dot-3; }
.pl-art-glass { animation-name: pl-art-glass; }
.pl-art-bar { transform-origin: bottom; }
.pl-art-bar.pl-art-0 { animation-name: pl-art-bar-0; } .pl-art-bar.pl-art-1 { animation-name: pl-art-bar-1; } .pl-art-bar.pl-art-2 { animation-name: pl-art-bar-2; } .pl-art-bar.pl-art-3 { animation-name: pl-art-bar-3; }
@keyframes pl-art-play { 0%, 86% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes pl-art-tag { 0%, 2% { opacity: 0; transform: translateY(-4px); } 8%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-line { 0%, 6% { stroke-dashoffset: 1; } 36%, 100% { stroke-dashoffset: 0; } }
@keyframes pl-art-dot-0 { 0%, 14% { opacity: 0; transform: scale(0); } 19%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-dot-1 { 0%, 20% { opacity: 0; transform: scale(0); } 25%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-dot-2 { 0%, 27% { opacity: 0; transform: scale(0); } 32%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-dot-3 { 0%, 34% { opacity: 0; transform: scale(0); } 39%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-glass { 0%, 38% { opacity: 0; transform: translateX(22px); } 50%, 100% { opacity: 1; transform: none; } }
@keyframes pl-art-bar-0 { 0%, 50% { transform: scaleY(0); } 57%, 100% { transform: none; } }
@keyframes pl-art-bar-1 { 0%, 53% { transform: scaleY(0); } 60%, 100% { transform: none; } }
@keyframes pl-art-bar-2 { 0%, 56% { transform: scaleY(0); } 63%, 100% { transform: none; } }
@keyframes pl-art-bar-3 { 0%, 59% { transform: scaleY(0); } 66%, 100% { transform: none; } }
/* The shelf an address landed on is outlined for a moment, and the outline fades. */
.pl-landed > .pl-list { outline: 2px solid var(--act); outline-offset: 3px; animation: pl-landed 2.4s ease forwards; }
@keyframes pl-landed { 70% { outline-color: var(--act); } 100% { outline-color: transparent; } }
@media (prefers-reduced-motion: reduce) { .pl-banner-art * { animation: none !important; } .pl-landed > .pl-list { animation: none; } }
@media (max-width: 40rem) { .pl-banner-art, .pl-banner-tiles { display: none; } }
.pl-shelf { margin-bottom: var(--space-7); }
.pl-shelf-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: var(--space-4); }
.pl-shelf-head h2 { margin: 0; font-size: var(--size-lead); line-height: var(--leading-tight); }
.pl-showall { color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); text-decoration: none; }
.pl-showall:hover { text-decoration: underline; }
.pl-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; grid-auto-flow: row dense; gap: var(--space-5); }
@media not (min-width: 48rem) { .pl-cards { grid-template-columns: minmax(0, 1fr); } }
.pl-card { position: relative; display: flex; gap: var(--space-5); min-height: 6.5rem; padding: var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--hover); }
.pl-card:hover { border-color: var(--edge); cursor: pointer; }
@media (max-width: 56rem) { .pl-tools { flex: 1 1 100%; min-width: 0; justify-content: flex-end; margin-left: 0; } .pl-searchbox { flex: 0 1 15rem; min-width: 0; } }
.pl-card-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); padding-right: var(--space-8); }
.pl-card-name { color: var(--ink); font-size: var(--size-body); font-weight: var(--weight-strong); line-height: var(--leading-tight); text-decoration: none; }
/* A shelf's card is as tall as its name, its two lines and its last line a step under them. */
.pl-card-open { height: 7rem; }
.pl-card-open:has(.pl-needs-row) { height: auto; min-height: 7rem; }
.pl-card-open .pl-card-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-card-open .pl-card-name::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-large); }
.pl-card-open .pl-card-name:focus-visible { outline: none; }
.pl-card-open:has(.pl-card-name:focus-visible) { outline: 2px solid var(--act); outline-offset: 2px; }
.pl-card-open .pl-meta { flex-wrap: nowrap; overflow: hidden; white-space: nowrap; }
/* A card keeps two lines' room for what it says, on a shelf and listed in an install card, so a card with one line is as tall as its neighbours. */
.pl-card-open .pl-about, .pl-card-link .pl-about { min-height: calc(2em * var(--leading-small)); }
.pl-card-open .pl-by { flex: none; }
/* A chip stands a step further from the by-line than from the chip before it. */
.pl-by { margin-right: var(--space-1); }
.pl-card-open .pl-act, .pl-card-open .pl-act-doing, .pl-card-open .pl-done-mark, .pl-card-open .pl-needs-row { z-index: 1; }
.pl-card-open .pl-needs-row { position: relative; }
.pl-about { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-top: auto; color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-act { position: absolute; top: var(--space-5); right: var(--space-5); display: grid; place-items: center; width: 1.75rem; height: 1.75rem; padding: 0; border-radius: var(--radius); font-size: var(--size-body); line-height: var(--leading-glyph); }
.pl-done-mark { position: absolute; top: var(--space-5); right: var(--space-5); display: grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: var(--radius); background: var(--wash); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-glyph); }
.pl-done { display: inline-flex; align-items: center; gap: var(--space-3); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-done .pl-done-mark { position: static; }
.pl-done-word { color: var(--ink); }
.pl-chip, .pl-tag { padding: 0 var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-small); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); white-space: nowrap; }
.pl-chip-paid { color: var(--ink); }
.pl-from { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); white-space: nowrap; }
.pl-from .pl-icon { width: 0.8rem; height: 0.8rem; }
/* Which plugin brings a row onto another's list is a phrase, not a mark: it keeps to the row's words and breaks where they end. */
.pl-need .pl-from { white-space: normal; }
.pl-tile-big { width: 3rem; height: 3rem; border-radius: var(--radius-large); background: var(--hover); font-size: var(--size-title); line-height: var(--leading-tight); }
/* A letter in the large tile is quiet; a mark keeps the ink. */
.pl-tile-big:not(:has(svg)) { color: var(--quiet); }
/* A mark takes one share of its tile at every size a tile is drawn, and a tile that holds a mark is the surface a list and a card are: darker than the page, and one tone with the row or card it lies on. */
.pl-logo svg { width: 56%; height: 56%; }
.tile .pl-icon { width: 60%; height: 60%; }
.tile.pl-logo, .tile:has(> .pl-icon) { background: var(--hover); }
/* A list and a card are the darker of the two surfaces, a step short of the wash a band or a note inside one is filled with; a dialog is that surface too, so a list or a card inside one is one tone with it. */
.pl-list { margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--hover); }
.pl-list > li + li { border-top: 1px solid var(--line); }
/* The line of what a row lacks joins its row with no edge between, and its own edge is under it. */
.pl-list .pl-needs-row { margin: 0; padding-left: calc(2.5rem + 2 * var(--space-5)); border-width: 0 0 1px; border-radius: unset; }
.pl-list > li:last-child > .pl-needs-row:last-child { border-bottom-left-radius: var(--radius-large); border-bottom-right-radius: var(--radius-large); }
.pl-row { display: flex; align-items: center; gap: var(--space-5); min-height: 3.2rem; padding: var(--space-3) var(--space-5); color: inherit; text-decoration: none; }
a.pl-row:hover { background: var(--wash); }
/* A row that is a link says so under the pointer in its name, as a link in a sentence does: the wash alone is a step the eye barely tells from the list. */
a.pl-row:hover .pl-row-name > strong, a.pl-row:hover .pl-row-text > strong, a.pl-side-row:hover .pl-side-word { text-decoration: underline; }
.pl-list > li:first-child > .pl-row { border-top-left-radius: var(--radius-large); border-top-right-radius: var(--radius-large); }
.pl-list > li:last-child > .pl-row:last-child { border-bottom-left-radius: var(--radius-large); border-bottom-right-radius: var(--radius-large); }
.pl-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* A row's second line is read whole, on as many lines as it takes; in a list of what is held, of skills or of what a plugin uses it keeps to one line and is cut. */
.pl-row-text > .quiet { overflow: hidden; text-overflow: ellipsis; font-size: var(--size-small); line-height: var(--leading-small); }
.pl-rows .pl-row-text > .quiet { white-space: nowrap; }
/* On a bundle's list a row's words keep a measure they can be read in: where the chips beside them would leave less, the chips take a line of their own, at the row's end. */
.pl-members .pl-row { flex-wrap: wrap; justify-content: flex-end; row-gap: var(--space-2); }
.pl-members .pl-row-text { flex: 1 1 6rem; }
.pl-row-chips { flex: none; display: flex; align-items: center; gap: var(--space-5); }
/* Why a plugin is on another's list is read whole: a line of its own under the row's two, from the words' edge, on as many lines as it takes. */
.pl-row:has(> .pl-reason) { flex-wrap: wrap; row-gap: 0; }
.pl-row > .pl-reason { flex: none; width: 100%; padding-left: calc(1.8rem + var(--space-5)); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-row-name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.pl-month, .pl-count { flex: none; color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); font-variant-numeric: tabular-nums; }
/* What a row says it spent this month is the row's quiet word in the money's face; an amount standing alone at a row's end is money's. */
.pl-month.money { color: var(--money); }
.pl-month-said.money { color: var(--quiet); }
.pl-needs { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); padding: var(--space-4) var(--space-5); margin: 0 0 var(--space-5); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--wash); font-size: var(--size-body); line-height: var(--leading-body); }
/* On a page the line is the page's own sentence with a button of the page's height; under a row or a card it is the row's smaller line, its button a step under the row's words. */
.pl-needs button { font-size: var(--size-body); line-height: var(--leading-body); }
.pl-needs > a.button { font-size: var(--size-body); line-height: var(--leading-body); }
/* The press in an account's line under the title is a link to the membership, drawn as the band's button: its words stay on one line at
   the band's size, and the sentence beside it wraps instead, where the band would shrink both and break 订阅会员 in two on a phone. */
.pl-account > a.button { flex: none; white-space: nowrap; }
.pl-needs-row { font-size: var(--size-small); line-height: var(--leading-small); }
.pl-needs-row button { padding: var(--space-1) var(--space-4); font-size: var(--size-caption); line-height: var(--leading-small); }
.pl-empty { padding: var(--space-6) 0 var(--space-7); }
.pl-empty p { margin: 0; font-size: var(--size-body); line-height: var(--leading-body); }
/* That a search found nothing is said in the small step, over the body-size way on. */
.pl-nomatch p { font-size: var(--size-small); line-height: var(--leading-small); }
.pl-empty button { margin-top: var(--space-3); font-size: var(--size-body); line-height: var(--leading-body); }
/* Its words set its width, up to the limit; where they take two lines the lines are even, and Chinese breaks only at a stop or a space. */
.pl-toast { position: fixed; z-index: 20; left: 1rem; right: 1rem; bottom: var(--space-7); width: fit-content; max-width: min(34rem, calc(100vw - 2rem)); margin: 0 auto; text-wrap: balance; word-break: keep-all; overflow-wrap: anywhere; padding: var(--space-3) var(--space-5); border-radius: var(--radius); background: var(--ink); color: var(--ground); font-size: var(--size-small); line-height: var(--leading-small); opacity: 0; pointer-events: none; }
.pl-toast.on { opacity: 1; pointer-events: auto; }
.pl-toast-act { white-space: nowrap; }
.pl-toast-first.pl-toast-break { display: block; }

/* Words for a screen reader alone. */
.unseen { position: absolute; top: 0; left: 0; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.pl-item .back, .pl-page > .back { margin: var(--space-8) 0 var(--space-4); }
.pl-loading { margin: 0; font-size: var(--size-body); line-height: var(--leading-body); }
.pl-item .back a, .pl-inline, .pl-credit a, .pl-side a { color: var(--quiet); text-decoration: none; }
.pl-item .back a:hover, .pl-inline:hover, .pl-credit a:hover, .pl-side a:hover { color: var(--ink); }
.pl-head { display: flex; align-items: center; gap: var(--space-5); margin-bottom: var(--space-6); }
.pl-head-text { flex: 1; min-width: 0; }
.pl-head-text h1 { margin: 0; font-size: var(--size-display); line-height: var(--leading-tight); }
.pl-head-text p { margin: var(--space-1) 0 0; }
.pl-head-tools { flex: none; display: flex; align-items: center; gap: var(--space-4); }
.pl-menu { position: relative; }
.pl-more { width: 2rem; height: 2rem; padding: 0; border: none; background: none; font-size: var(--size-lead); line-height: var(--leading-glyph); }
.pl-menu-list { position: absolute; z-index: 5; right: 0; top: calc(100% + var(--space-2)); display: flex; flex-direction: column; min-width: 10rem; padding: var(--space-2); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--hover); box-shadow: none; }
.pl-menu-list[hidden] { display: none; }
.pl-menu-list button { border: none; background: none; text-align: left; }
.pl-menu-list .pl-remove, .pl-menu-list .pl-busy { padding: var(--space-3) var(--space-4); border-radius: var(--radius-small); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-switch { display: inline-flex; align-items: center; gap: var(--space-3); padding: 0; border: none; background: none; color: var(--quiet); }
.pl-switch:hover:not(:disabled) { background: none; color: var(--ink); }
.pl-switch-track { position: relative; width: 2rem; height: 1.15rem; border: 1px solid var(--edge); border-radius: var(--radius-round); background: var(--wash); }
.pl-switch-knob { position: absolute; top: 1px; left: 1px; width: calc(1.15rem - 4px); height: calc(1.15rem - 4px); border-radius: var(--radius-round); background: var(--quiet); }
.pl-switch[aria-checked="true"] .pl-switch-track { border-color: var(--act); background: var(--act); }
.pl-switch[aria-checked="true"] .pl-switch-knob { left: calc(100% - 1.15rem + 3px); background: var(--act-ink); }
.pl-switch-word { font-size: var(--size-small); line-height: var(--leading-small); }
.pl-switch-track { order: 1; }
/* A switch that cannot be turned is its track faded: the word beside it stays ink, and nothing is filled under the two. */
.pl-switch:disabled { border: none; background: none; }
.pl-switch:disabled .pl-switch-track { opacity: 0.45; }
.pl-switch:disabled .pl-switch-word { color: var(--ink); }
.pl-tabs { display: flex; gap: var(--space-2); border-bottom: 1px solid var(--line); overflow-x: auto; }
.pl-tab { padding: var(--space-3) var(--space-5); white-space: nowrap; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--quiet); text-decoration: none; }
/* On a phone a vendor's four tabs fit the bar with narrower sides, so Settings is not cut at its edge. */
@media not (min-width: 30rem) { .pl-tab { padding-inline: var(--space-4); } }
.pl-tab:hover { color: var(--ink); }
/* The tab bar scrolls sideways, so it clips what is drawn outside it: a tab's ring is drawn inside the tab. */
.pl-tab:focus-visible { outline-offset: -2px; }
.pl-tab[aria-selected="true"] { border-bottom-color: var(--ink); color: var(--ink); font-weight: var(--weight-strong); }
.pl-tab-count { color: var(--quiet); font-size: var(--size-small); font-weight: var(--weight-regular); }
.pl-columns { display: grid; grid-template-columns: minmax(0, 1fr) 16rem; gap: var(--space-8); }
/* The tab's body starts a step under the tab rule, and what comes first adds its own: a heading two steps more, a quiet sentence one, a sentence half of one. A heading keeps its two steps over it wherever it comes, so the gaps between a tab's parts are one rule. */
.pl-tabbody { padding-top: var(--space-4); }
:where(.pl-tabbody) p { margin: 0 0 var(--space-2); }
.pl-tabbody > p:first-child { margin-top: var(--space-2); }
.pl-tabbody > p.quiet:first-child { margin-top: var(--space-4); }
.pl-tabbody > .pl-list:first-child { margin-top: calc(-1 * var(--space-1)); }
.pl-main section, .pl-tabbody > section { margin-bottom: var(--space-2); }
.pl-main h2, .pl-tabbody h2 { margin-top: var(--space-6); }
.pl-tabbody .pl-table + p { margin-top: var(--space-2); }
.pl-head + .pl-tabbody > h2:first-child { margin-top: var(--space-4); }
/* The optional plugins are a list of their own, three steps under the required ones. */
.pl-need + .pl-need > h2 { margin-top: var(--space-7); }
.pl-main h2, .pl-tabbody h2, .pl-side h2 { margin-bottom: var(--space-3); margin-left: 0; margin-right: 0; color: var(--quiet); font-size: var(--size-small); font-weight: var(--weight-strong); line-height: var(--leading-small); }
.pl-main > p, .pl-main > section > p { max-width: 40rem; }
/* Under a part's closing hairline a heading stands three steps down and a sentence or a button a step and a half. */
.pl-tabbody > .pl-setting { margin-bottom: var(--space-3); padding-bottom: var(--space-6); border-bottom: 1px solid var(--line); }
.pl-setting + .pl-setting { padding-top: var(--space-4); }
.pl-setting + .pl-setting > h2:first-child { margin-top: var(--space-5); }
.pl-setting p { max-width: 38rem; margin: 0 0 var(--space-2); }
.pl-setting > p:last-child { margin-bottom: 0; }
/* One sentence under another, and a list or a table under its sentence, stand half a step off; a README keeps its own paragraphs apart. */
.pl-main p { margin: 0 0 var(--space-2); }
.pl-readme p { margin-bottom: var(--space-3); }
.pl-side { align-self: start; margin-top: var(--space-6); padding: var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--hover); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-side h2 { margin-top: 0; }
.pl-side p { margin: 0; }
.pl-maker { margin-top: var(--space-5); padding-top: var(--space-5); border-top: 1px solid var(--line); }
.pl-maker:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.pl-maker p + p { margin-top: var(--space-3); }
.pl-side .pl-maker a, .pl-side .pl-maker a:hover { color: var(--act); text-decoration: underline; white-space: nowrap; }
.pl-plain { margin: 0; padding-left: var(--space-6); }
.pl-side .pl-plain { padding-left: 0; list-style: none; }
.pl-tries { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.pl-tries > li { max-width: 100%; }
.pl-try { max-width: 100%; padding: var(--space-3) var(--space-5); text-align: left; font-size: var(--size-small); line-height: var(--leading-small); }
.pl-table { width: 100%; border-collapse: collapse; font-size: var(--size-small); line-height: var(--leading-small); }
.pl-table th { padding: var(--space-2) var(--space-5) var(--space-2) 0; border-bottom: 1px solid var(--line); color: var(--quiet); font-size: var(--size-caption); font-weight: var(--weight-regular); text-align: left; }
.pl-table td { padding: var(--space-3) var(--space-5) var(--space-3) 0; border-bottom: 1px solid var(--line); vertical-align: middle; }
.pl-table th:last-child, .pl-table td:last-child { padding-right: 0; }
.pl-table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* A figure keeps one line at every width; a table of models folds its price between its two figures instead. */
.pl-table:not(.pl-models) .num { white-space: nowrap; }
.pl-table td.num:not(.quiet) { font-family: var(--font-mono); }
.pl-list > li > .pl-row > .tile { width: 1.8rem; height: 1.8rem; }
@media not (min-width: 40rem) { .pl-table .pl-meter { width: 2.5rem; } }
/* On a phone nothing is read by dragging the page sideways: the tabs stay one line that scrolls inside its own strip, and a table of models gives its width to the names — the tick's column is its box, a price breaks at its stroke, a long name takes a second line, and a series' six columns stand a step closer. */
@media not (min-width: 40rem) { .pl-series .pl-tick { width: auto; } .pl-models .pl-meter { width: 2rem; } .pl-models .pl-model-name strong { max-width: none; white-space: normal; overflow-wrap: anywhere; } .pl-series th, .pl-series td { padding-right: var(--space-4); } }
/* The height the prototype's two-line row has; the one line drawn today stands in its middle. */
.pl-model-rows .pl-models tbody td { height: 3.4375rem; }
/* A series' versions, unfolded under it, take the height of their own lines. */
.pl-model-rows .pl-models tbody tr.pl-version td { height: auto; }
/* A series' row has its two lines and is as tall as they are: the tick and the bars stand beside the first, the series' name. */
.pl-model-rows .pl-series tbody td { height: auto; vertical-align: top; }
.pl-series th { vertical-align: top; }
.pl-series td.pl-tick { padding-top: var(--space-4); }
.pl-series td.pl-rated { padding-top: var(--space-6); }
.pl-nobreak { white-space: nowrap; }
/* A bar on a version's row keeps its track: the row is the wash every other track is, so the track there is the next tint of ink. */
.pl-version td { background: var(--wash); }
.pl-version .pl-meter { background: var(--line); }
.pl-version .pl-mname { font-weight: var(--weight-regular); }
.pl-tick { width: 4.5rem; }
.pl-tick input { display: block; width: 1rem; height: 1rem; margin: 0; }
.pl-mname { display: flex; align-items: center; gap: var(--space-3); }
/* A series' or a version's name with no place to break wraps inside its column rather than push the table and its price past the page. */
.pl-series .pl-mname, .pl-series .pl-mname strong, .pl-series .pl-msub { overflow-wrap: anywhere; }
.pl-series .pl-mname { flex-wrap: wrap; }
@media (min-width: 24rem) { .pl-series .pl-mname { min-width: 4.5rem; } }
/* On a phone the tick's column is as wide as its box: its heading is read, not shown; the line above the table says what a tick does. */
@media not (min-width: 40rem) { .pl-series th.pl-tick > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }
/* The way to the page that has room, inside the line that says why there is none, in the line's own ink. */
.vc-fact a { color: inherit; text-decoration: underline; }
.pl-msub { display: block; }
.pl-disclose { display: inline-flex; align-items: center; gap: var(--space-2); padding: 0; border: none; border-radius: var(--radius-small); background: none; font: inherit; color: inherit; text-align: left; }
.pl-disclose:hover:not(:disabled) { background: none; }
.pl-caret { color: var(--quiet); font-size: var(--size-caption); }
.pl-disclose:hover .pl-caret { color: var(--ink); }
.pl-media-switch .pl-switch { vertical-align: middle; }
.pl-meter { position: relative; display: block; width: 6rem; max-width: 100%; height: 0.3rem; border-radius: var(--radius-round); background: var(--wash); cursor: default; outline-offset: var(--space-2); }
/* The bar is thin: the pointer finds its figure from a taller place around it. */
.pl-meter::before { content: ""; position: absolute; inset: calc(-1 * var(--space-5)) 0; }
.pl-meter-fill { display: block; height: 100%; border-radius: var(--radius-round); background: var(--quiet); }
.pl-meter:hover .pl-meter-fill, .pl-meter:focus-visible .pl-meter-fill { background: var(--ink); }
.pl-tip { display: none; position: absolute; bottom: 0.9rem; left: 0; z-index: 3; padding: var(--space-2) var(--space-4); border: 1px solid var(--edge); border-radius: var(--radius-small); background: var(--ground); color: var(--ink); font-family: var(--font-ui); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
.pl-meter:hover > .pl-tip, .pl-meter:focus-visible > .pl-tip { display: block; }
.pl-news { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); margin: var(--space-2) 0 var(--space-5); padding: var(--space-4) var(--space-5); border: 1px solid var(--line); border-radius: var(--radius-large); background: var(--wash); font-size: var(--size-body); line-height: var(--leading-body); }
.pl-list .pl-news-row { margin: 0; border-width: 1px 0 0; border-radius: unset; }
.pl-list > li:last-child > .pl-news-row:last-child { border-bottom-left-radius: var(--radius-large); border-bottom-right-radius: var(--radius-large); }
.pl-news-acts { display: flex; flex: none; gap: var(--space-3); }
/* Update's ✓ stands where Update stood, its size, so the line does not move. */
.pl-news .pl-done-mark { position: static; width: auto; min-width: 1.75rem; height: auto; padding: var(--space-2) var(--space-4); border: 1px solid transparent; background: none; font-size: var(--size-body); line-height: var(--leading-body); }
.pl-updates { margin: 0 0 var(--space-6); }
/* A press being written down turns a ring where its control stood, on the chat's running-step ground, its words for a screen reader
   alone; a button that held words keeps their room, unseen, so its line neither shrinks nor moves. */
.pl-spin { display: inline-block; width: 0.9rem; height: 0.9rem; border: 2px solid var(--live-edge); border-top-color: var(--ink); border-radius: var(--radius-round); animation: pl-spin 0.8s linear infinite; }
@keyframes pl-spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { .pl-spin { animation-duration: 2.4s; } }
button.pl-hold { position: relative; }
.pl-hold-word { visibility: hidden; }
button.pl-hold .pl-spin { position: absolute; inset: 0; margin: auto; }
/* Update's ring stands still where motion is reduced, as signed; its place and its name still say the press is being written down. */
@media (prefers-reduced-motion: reduce) { button.pl-hold .pl-spin { animation: none; } }
/* The reminder that plugins have a new version: a filled dot after the word it marks. */
.pl-new { display: inline-block; margin-left: var(--space-2); border-color: var(--ink); background: var(--ink); vertical-align: middle; }
/* A button takes the size step of the words it sits with: beside the page's own sentences, the body's. */
.pl-head-tools button.primary, .pl-news button, .pl-way-act button, .pl-up, .pl-tabbody > p > button, .pl-banner-text button, .pl-create { font-size: var(--size-body); line-height: var(--leading-body); }
.pl-banner-text a.button { padding-top: var(--space-3); padding-bottom: var(--space-3); border-color: var(--line); }
/* The banner's link lies on the wash, where the site's fill under the pointer is a step too slight to see: its edge answers. */
.pl-banner-text a.button:hover { border-color: var(--edge); }
.pl-setting .pl-choose a.button { border-color: var(--line); }
/* Its fill under the pointer is the site's, a shade on the page's ground; its edge answers, as the banner's link and a quiet button's do. */
.pl-setting .pl-choose a.button:hover { border-color: var(--edge); }
/* On the Plugins page and in its cards a control is filled with the surface a list and a card are, inside the faint edge: a quiet button, a field and a tick box are darker than the page they lie on and one tone with a row or a card they lie on. Under the pointer a button is the wash, and since the wash is a step the eye barely tells from the surface, its edge goes to a control's, as a shelf card's does. */
:where(.pl-page, .pl-card-dialog) button, :where(.pl-page, .pl-card-dialog) select, :where(.pl-page, .pl-card-dialog) input { border-color: var(--line); background: var(--hover); }
:where(.pl-page, .pl-card-dialog) button:hover:not(:disabled) { border-color: var(--edge); background: var(--wash); }
/* A drop-down is a field: the browser sizes it by its own line, so the field's height is stated. */
:where(.pl-page, .pl-card-dialog) select { height: calc(1em * var(--leading-body) + 2 * var(--space-2) + 2px); font-size: var(--size-body); }
.pl-news .pl-quietbtn, .pl-quietbtn { border-color: transparent; background: none; color: var(--quiet); }
/* A quiet button has no fill to change, so it answers the pointer in its words. */
.pl-quietbtn:hover:not(:disabled) { border-color: transparent; background: none; color: var(--ink); }
.pl-way-row { flex-wrap: wrap; }
.pl-way-row > .pl-row-text { flex: 1 1 12rem; }
.pl-main a.pl-inline, .pl-tomonth a.pl-inline, .pl-tabbody > .pl-choose a.pl-inline { color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-main a.pl-inline:hover, .pl-tomonth a.pl-inline:hover, .pl-tabbody > .pl-choose a.pl-inline:hover, .pl-card-body a.pl-inline:hover { text-decoration: underline; }
.pl-main .pl-choose { margin-top: var(--space-4); }
.pl-tabbody > .pl-choose { margin-top: var(--space-3); }
.pl-main .pl-choose a.pl-inline { color: var(--quiet); text-decoration: underline; }
.pl-go { flex: none; color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
/* Wide enough for the longest "Paste your … API key" a vendor or host gives: "Vercel AI Gateway" in English needs about 255px of the 270 this leaves inside the padding. */
.pl-key { width: 18rem; }
.pl-setting .pl-note { min-height: 1.4rem; }
/* A tab's headline figure is in the figures' face, money or not. */
.pl-big { font-family: var(--font-mono); font-size: var(--size-title); line-height: var(--leading-tight); font-variant-numeric: tabular-nums; }
.pl-days { display: flex; align-items: flex-end; gap: 3px; height: 6rem; padding-bottom: 1px; border-bottom: 1px solid var(--line); }
.pl-day { flex: 1; height: 100%; display: flex; align-items: flex-end; }
.pl-day > span { display: block; width: 100%; min-height: 1px; background: var(--money); border-radius: var(--radius-small) var(--radius-small) 0 0; }
.pl-axis { display: flex; justify-content: space-between; margin-top: var(--space-1); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); font-variant-numeric: tabular-nums; }
.pl-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.pl-bordered { border: 1px solid var(--line); border-radius: var(--radius-large); }
.pl-bordered > li { padding: var(--space-4) var(--space-5); }
/* The row inside takes the list item's padding and adds none. */
.pl-bordered > li > .pl-row { min-height: 0; padding: 0; }
.pl-bordered > li:last-child { border-bottom: 0; }
.pl-way-act { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--space-4); margin-left: auto; }
.pl-way-act > .quiet { align-self: center; }
/* A field and its Save share a line; on a phone Save goes under the field. */
.pl-fieldrow { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--space-4); max-width: 38rem; margin: var(--space-2) 0; }
.pl-fieldrow > input { flex: 1 1 16rem; min-width: 0; color: var(--ink); font-size: var(--size-body); line-height: var(--leading-body); }
.pl-label { margin-top: var(--space-5); }
.pl-saved { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-5); }
.pl-after, .pl-setting .pl-after { margin: var(--space-4) 0 0; }
.pl-field-note:empty { display: none; }
.pl-field-note { flex-basis: 100%; margin: 0; }
.pl-model-name strong { display: inline-block; max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.pl-model-name .pl-tag { margin-left: var(--space-2); }
.pl-side a.pl-side-row { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-2); border-radius: var(--radius-small); color: inherit; }
.pl-side a.pl-side-row:hover { background: var(--wash); color: inherit; }
.pl-side-row .tile { width: 1.6rem; height: 1.6rem; }
.pl-side-name { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: var(--leading-tight); }
.pl-side-name .quiet { font-size: var(--size-caption); line-height: var(--leading-small); }
.pl-list > li { position: relative; }
.pl-row-act { top: var(--space-5); right: var(--space-5); }
/* A row's lone chevron stands in the column a tick takes; a way's words — Connected, Set up — keep their own width. */
.pl-row > .pl-go[aria-hidden] { width: 1.75rem; text-align: center; }
.pl-price { flex: none; font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
.pl-card .pl-price { white-space: normal; }
.pl-list > li:has(.pl-row-act) .pl-row, .pl-list > li:has(.pl-act-ring) .pl-row { padding-right: calc(1.75rem + 2 * var(--space-5)); }
.pl-said { margin: 0 0 var(--space-4); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
/* A gap's chip fits the line it stands in, so a prompt with one is as tall as a prompt without. */
.pl-gap { display: inline-block; padding: 0 var(--space-3); border: 1px dashed var(--edge); border-radius: var(--radius-small); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-tight); }
.pl-up { flex: none; }
.pl-order-n { flex: none; display: grid; place-items: center; width: 1.4rem; height: 1.4rem; border: 1px solid var(--line); border-radius: var(--radius-round); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-glyph); }
@media (max-width: 56rem) { .pl-columns { grid-template-columns: minmax(0, 1fr); } }
/* Folded under, the column that holds only the note nobody checked the plugin goes above its README, which may run for screens. */
@media (max-width: 56rem) { .pl-side-first { order: -1; } }

/* The cards: install, remove, turn off and turn on, one drawing; Remove acts in forest like any act. */
/* A card opens at its title with the keyboard on its middle. Taller than the screen, its middle scrolls: the title, what an install buys and the buttons stay in view. */
/* A card is the surface a list and a card on the page are, inside the faint edge a menu has. */
dialog.pl-card-dialog { width: min(34rem, calc(100vw - var(--space-8))); max-width: none; max-height: calc(100vh - var(--space-8)); overflow: hidden; border-color: var(--line); background: var(--hover); }
dialog.pl-card-dialog[open] { display: flex; flex-direction: column; }
dialog.pl-card-dialog > * { flex: none; }
/* The middle clips what it scrolls: the room around it holds the keyboard's ring whole, and so does the room the browser leaves when it scrolls what the keyboard reaches into view. */
dialog.pl-card-dialog > .pl-card-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: calc(-1 * var(--space-2) - 1px) calc(-1 * var(--space-2)); padding: var(--space-2); border: solid transparent; border-width: 1px 0; scroll-padding-block: var(--space-3); }
/* Where the middle is cut, above or below, a rule says it goes on. The edge is always there and only its colour changes, so the rule moves nothing. */
dialog.pl-card-dialog > .pl-card-body[data-more~="above"] { border-top-color: var(--line); }
dialog.pl-card-dialog > .pl-card-body[data-more~="below"] { border-bottom-color: var(--line); }
dialog.pl-card-dialog:has(.pl-installs) { width: min(44rem, calc(100vw - var(--space-8))); }
dialog.pl-card-dialog:focus, .pl-card-body:focus { outline: none; }
/* What an install buys without asking stands with the buttons, outside what scrolls. */
.pl-card-foot { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-6); }
.pl-card-foot > p { margin: 0; }
.pl-card-foot:empty { display: none; }
/* What stands under a card's head: a sentence or the label of what it installs four steps down, the label of what stops or a field three, the line about a stranger's code two. */
.pl-card-head { display: flex; align-items: center; gap: var(--space-5); margin-bottom: var(--space-6); }
.pl-card-head:has(+ .pl-card-body > .pl-block:first-child) { margin-bottom: var(--space-5); }
.pl-card-head:has(+ .pl-card-body > .pl-leaves:first-child) { margin-bottom: var(--space-4); }
.pl-card-body a.pl-inline { color: var(--ink); }
.pl-card-head h2 { margin: 0; }
.pl-card-body { display: flex; flex-direction: column; gap: var(--space-5); }
.pl-card-body p, .pl-card-body h3 { margin: 0; }
/* One sentence under another stands a whole step off, in the card's own column and inside one of its parts. */
.pl-card-body > p + p { margin-top: var(--space-2); }
.pl-card-body section > p + p { margin-top: var(--space-6); }
.pl-card-body h3 { margin-bottom: var(--space-2); color: var(--quiet); font-size: var(--size-small); font-weight: var(--weight-strong); line-height: var(--leading-small); }
/* What a card installs and what it buys: each part four steps under the one before, its label two steps over its cards or its list, the sentence about the rest three under the cards and the rule's sentence four under the list. */
.pl-installs + .pl-installs { margin-top: var(--space-2); }
.pl-installs h3 { margin-bottom: var(--space-4); }
.pl-installs > .pl-cards ~ p.quiet { margin-top: var(--space-5); }
/* A sentence stands four steps over its table. */
.pl-card-body > p + .pl-table { margin-top: var(--space-2); }
.pl-card-body .pl-cards { gap: var(--space-4); }
.pl-card-link { display: block; color: var(--ink); text-decoration: none; border-radius: var(--radius-large); }
.pl-card-link > .pl-card { height: 100%; min-height: 0; }
.pl-card-link .pl-card-text { padding-right: 0; }
.pl-installs .pl-list { margin: 0; }
.pl-block ul { margin: 0; padding-left: var(--space-6); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-block li + li { margin-top: var(--space-1); }
/* A part named with what stops is two lines, so the next part stands two steps under it. */
.pl-block li:has(> .pl-stop-one) + li { margin-top: var(--space-4); }
.pl-stop-one { display: flex; flex-direction: column; gap: var(--space-1); }
.pl-rule { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-6); margin-top: var(--space-4); }
.pl-rule .pl-more-link { flex: none; white-space: nowrap; }
.pl-more-link { padding: 0; border: none; background: none; color: var(--quiet); font-size: var(--size-small); }
.pl-more-link:hover { color: var(--ink); }
.pl-leaves { display: flex; gap: var(--space-3); padding-bottom: var(--space-4); border-bottom: 1px solid var(--line); }
.pl-glyph { flex: none; width: 1.15rem; color: var(--quiet); text-align: center; }
.pl-card-acts { justify-content: flex-end; gap: var(--space-5); margin: var(--space-6) 0 0; }
.pl-card-acts button { font-size: var(--size-body); line-height: var(--leading-body); }
/* An act that cannot be pressed yet is itself, faded. */
.pl-card-acts button.primary:disabled { border-color: var(--act); background: var(--act); color: var(--act-ink); opacity: 0.45; }
dialog.pl-tool-dialog .pl-tool-title { margin: 0 0 var(--space-6); }
dialog.pl-tool-dialog .pl-tool-title:has(+ .pl-card-body > .pl-field:first-child) { margin-bottom: var(--space-5); }
.pl-tool-failed { margin: var(--space-5) 0 0; }
.pl-tool-failed:empty { display: none; }
.pl-field { display: flex; flex-direction: column; gap: var(--space-2); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-field input { color: var(--ink); }
/* A field a person writes in is as tall as a field on the page. */
.pl-field input[type="text"] { font-size: var(--size-body); line-height: var(--leading-body); }
/* A store's form: one field a line, every field as tall as a field on the page. */
.pl-store-form { display: grid; gap: var(--space-5); max-width: 24rem; margin: var(--space-5) 0; }
.pl-store-form .pl-store-field { width: 100%; color: var(--ink); font-size: var(--size-body); line-height: var(--leading-body); }
.pl-setting .pl-after { margin: var(--space-4) 0 0; }
.pl-setting .pl-failed { max-width: 38rem; margin: var(--space-4) 0 0; }
.pl-store-words { overflow-wrap: anywhere; }
.pl-card-body > .pl-or { margin: calc(-1 * var(--space-2)) 0; }
.pl-card-body > .pl-field-note { color: var(--ink); }
.pl-pick { max-height: 16rem; overflow-y: auto; scroll-padding-block: var(--space-3); }
.pl-pick .pl-row { min-height: 2.6rem; cursor: pointer; }
/* A tick row under the pointer, as a menu's row: the ground cut from the list's own. */
.pl-pick label.pl-row:hover { background: var(--float-hover); }
.pl-pick .pl-row input { flex: none; margin: 0; }
.pl-pick-chips { flex: none; display: flex; gap: var(--space-3); }
.pl-needs-act { color: var(--ink); white-space: nowrap; }
.pl-doing { display: inline-flex; align-items: baseline; gap: var(--space-3); color: var(--ink); font-size: var(--size-caption); line-height: var(--leading-small); white-space: nowrap; }
.pl-act-doing { position: absolute; top: var(--space-5); right: var(--space-5); display: grid; place-items: center; width: 1.75rem; height: 1.75rem; padding: 0; border: 1px solid var(--live-edge); border-radius: var(--radius); background: var(--live-wash); cursor: default; }
button.pl-busy { display: inline-flex; align-items: center; justify-content: center; border-color: var(--live-edge); background: var(--live-wash); color: var(--ink); cursor: default; }
.pl-switch-knob .pl-spin { display: block; width: 100%; height: 100%; box-sizing: border-box; border-width: 2px; }
.pl-switch[aria-busy="true"] .pl-switch-track { border-color: var(--live-edge); background: var(--live-wash); }
.pl-switch[aria-busy="true"] .pl-switch-knob { background: var(--live-wash); }
.pl-switch[aria-busy="true"] .pl-switch-word { color: var(--ink); }
.pl-switch[aria-disabled="true"] { cursor: default; }
.pl-list > li:has(.pl-act-doing) .pl-row .pl-doing { display: none; }
.pl-list > li:has(.pl-act-doing) .pl-row { padding-right: calc(1.75rem + 2 * var(--space-5)); }
.pl-card { flex-wrap: wrap; }
.pl-failed { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-4); margin: 0 0 var(--space-4); padding: var(--space-4) var(--space-5); border: 1px solid var(--bad-line); border-radius: var(--radius); color: var(--bad); font-size: var(--size-small); line-height: var(--leading-small); }
/* A line about one card is a row of its own under that card's row, so the card, its neighbour and their words stay as they were. */
.pl-cards > .pl-failed-card, .pl-cards > .pl-fact-card { grid-column: 1 / -1; margin: 0; }
.pl-fact { margin: 0 0 var(--space-4); padding: var(--space-4) var(--space-5); border: 1px solid var(--line); border-radius: var(--radius); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.pl-fact-row { margin: 0 var(--space-5) var(--space-5); }
.pl-failed-address { user-select: all; }
.pl-again, .pl-failed-help { display: inline-flex; align-items: center; min-height: 1.5rem; }
.pl-unchecked { color: var(--ink); }
.pl-failed-row { margin: 0 var(--space-5) var(--space-5); }
.pl-failed-text { flex: 1 1 14rem; min-width: 0; }
/* With the count and the help beside the try, the sentence has the row to itself at every width, in either language. */
.pl-failed:has(.pl-failed-count) .pl-failed-text { flex-basis: 100%; }
.pl-failed-acts { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-4); }
.pl-again { padding: 0 var(--space-3); }
.pl-failed-help { color: inherit; }
/* What stands under a card's title, the by-line or the sentence that names its parts, is a small step under it. */
.pl-card-headtext p { margin: var(--space-1) 0 0; }
.pl-card-by { font-size: var(--size-small); line-height: var(--leading-small); }
/* A README is a stranger's words under the page's own: its headings are its body's size in the strong weight, never smaller than what they head. */
.pl-readme h1, .pl-readme h2, .pl-readme h3, .pl-readme h4 { margin: var(--space-6) 0 var(--space-3); color: inherit; font-size: inherit; line-height: inherit; }
.pl-state { font-size: var(--size-small); line-height: var(--leading-small); color: var(--ink); }
.pl-readme > :first-child { margin-top: 0; }
/* A README's table keeps its words whole: wider than the column, it scrolls sideways inside its own frame. */
.pl-readme-table { overflow-x: auto; margin: var(--space-4) 0; }
.pl-readme-table table { display: table; width: max-content; }
.pl-readme-table th, .pl-readme-table td { overflow-wrap: normal; word-break: normal; }
/* A table wider than its column shows that it scrolls: a shadow stands at each edge with more beyond it, and goes once that edge is reached. */
.pl-readme-table {
  background: linear-gradient(to right, var(--ground) 30%, transparent) left / 2rem 100% no-repeat local, linear-gradient(to left, var(--ground) 30%, transparent) right / 2rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--line), transparent) left / 0.75rem 100% no-repeat scroll, radial-gradient(farthest-side at 100% 50%, var(--line), transparent) right / 0.75rem 100% no-repeat scroll;
}
/* A README's long command scrolls inside its box, as its table does, rather than widening the page; an address breaks anywhere. */
.pl-readme pre { overflow-x: auto; }
.pl-words, .pl-third-meta { overflow-wrap: anywhere; }
/* A link inside a README's text keeps its focus ring clear of the words beside it. */
.pl-readme a:focus-visible { outline-offset: 3px; border-radius: var(--radius-small); }

/* Discover's two sections: ComChatX's plugins, then the third-party ones under a hairline, each named at the title size. */
.pl-section-title { margin: 0 0 var(--space-6); font-size: var(--size-title); font-weight: var(--weight-strong); line-height: var(--leading-tight); }
.pl-section + .pl-section { margin-top: var(--space-8); padding-top: var(--space-8); border-top: 1px solid var(--line); }
.pl-section .pl-shelf-head h3 { margin: 0; font-size: var(--size-lead); font-weight: var(--weight-strong); line-height: var(--leading-tight); }
/* The kinds and the order stay at the window's top while the third-party list scrolls under them; a card the keyboard reaches stops under the bar. */
.pl-npm-bar { position: sticky; top: 0; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-5); margin: 0 0 var(--space-5); padding: var(--space-3) 0; border-bottom: 1px solid var(--line); background: var(--ground); }
.pl-kinds { flex-wrap: wrap; }
.pl-sort { margin-left: auto; }
/* A third-party card carries npm's facts, so its last line wraps rather than being cut, and the card grows to hold it. */
.pl-card-third.pl-card-open { height: auto; min-height: 7rem; }
.pl-card-third .pl-meta { display: block; white-space: normal; overflow: visible; }
.pl-card-third .pl-meta .pl-chip { margin-right: var(--space-3); }
.pl-card-third .pl-meta .pl-by { margin-right: 0; }
/* A fact npm gives is never broken across two lines; who made it and the version break only where one is longer than the line. */
.pl-npm-fact { white-space: nowrap; }
.pl-npm-whole { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.pl-npm-more { margin: var(--space-6) 0 0; text-align: center; }
/* pi's own words for a failure, quoted after the page's: they run on as one line of the failure's text. */
.pl-failed-words { color: var(--quiet); overflow-wrap: anywhere; }
/* An update pressed elsewhere: the card's ✓ turns the ring, where ✓ stood and in its room. */
.pl-act-ring { border-color: var(--live-edge); background: var(--live-wash); cursor: default; }
button.pl-act-doing:hover:not(:disabled), button.pl-busy:hover:not(:disabled) { border-color: var(--live-edge); background: var(--live-wash); }
button.pl-act-ring:hover:not(:disabled) { border-color: var(--live-edge); background: var(--live-wash); }
/* On a narrow window a finger presses these: each is as large as a finger, and the words beside + make room for it. */
@media not (min-width: 48rem) {
  .pl-act { width: 2.75rem; height: 2.75rem; }
  .pl-act-doing { width: 2.75rem; height: 2.75rem; }
  .pl-list > li:has(.pl-act-doing) .pl-row { padding-right: 4.25rem; }
  .pl-card-text { padding-right: 3.25rem; }
  .pl-list > li:has(.pl-row-act) .pl-row, .pl-list > li:has(.pl-act-ring) .pl-row { padding-right: 4.25rem; }
  .pl-more { min-width: 2.75rem; min-height: 2.75rem; }
  .pl-switch, .pl-again, .pl-failed-help, .pl-head-tools button.primary, .pl-card-acts button { min-height: 2.75rem; }
}

/* The page where the chat's models are chosen. Default stands apart above the vendors, as far from them as one shelf is from the next. */
.vc-default { margin-bottom: var(--space-7); }
.vc-mark::before { content: ""; width: 56%; height: 56%; background: url("./assets/favicon.svg") center / contain no-repeat; }
/* A vendor's name opens its page, in the row's ink, as a row that is a link draws its name. */
.vc-name { color: inherit; text-decoration: none; }
.vc-name:hover { text-decoration: underline; }
.vc-page .pl-row-name > strong { min-width: 0; overflow-wrap: anywhere; }
/* A row's words keep 10rem before its presses take a line of their own, which stand at the row's right edge. */
.vc-page .pl-way-row > .pl-row-text { flex-basis: 10rem; }
.vc-page .pl-way-act { justify-content: flex-end; }
.vc-alone { margin: 0; }
.vc-more { margin: var(--space-4) 0 0; }
.vc-page .pl-fact { margin-bottom: var(--space-4); }
.vc-choose { display: inline-flex; align-items: center; gap: var(--space-3); }
/* A link among a row's presses is drawn as the presses beside it are. */
.vc-page .pl-way-act a.button { display: inline-flex; align-items: center; border-color: var(--line); background: var(--hover); font-size: var(--size-body); line-height: var(--leading-body); }
.vc-page .pl-way-act a.button:hover { border-color: var(--edge); background: var(--wash); }
/* A vendor's series open under its row and start where its words start. */
.vc-chooser { padding: 0 var(--space-5) var(--space-5) calc(1.8rem + 2 * var(--space-5)); }
.vc-chooser .pl-model-rows > p:first-child { margin-top: 0; }
.vc-chooser .pl-model-rows p { margin: 0 0 var(--space-2); }
.vc-chooser .pl-table + p { margin-top: var(--space-3); }
.vc-chooser .pl-credit { margin-bottom: 0; }
@media not (min-width: 40rem) { .vc-chooser { padding-left: var(--space-5); } }

/* A host's list of many makers' series: the series in chat, then every series by maker, under one set of columns that stands still when a
   maker opens or a search narrows the list. The tick keeps its width, each rating a sixth of the table, the price its own room, the
   model the rest; on a phone each rating column holds its heading's longest word. */
.or-part + .or-part { margin-top: var(--space-7); }
.or-part > .pl-model-rows > p:first-child { margin-top: 0; }
.or-search { width: 18rem; max-width: 100%; margin: 0 0 var(--space-4); }
.or-table { table-layout: fixed; }
.or-table thead th:nth-child(n+3) { width: 17%; }
.or-table thead th.num { width: 9rem; }
/* A heading that wraps in its narrowed column wraps evenly: 每任务成本 reads 每任务 over 成本. */
.or-table thead th { text-wrap: balance; }
/* Without the tick, on an Overview before a host's models are reached, the ratings start one column sooner. */
.or-table.or-bare thead th:nth-child(2) { width: 17%; }
@media not (min-width: 40rem) {
  .or-table thead th.pl-tick { width: 1.75rem; }
  .or-table thead th:nth-child(3) { width: 5rem; }
  .or-table thead th:nth-child(4), .or-table thead th:nth-child(5) { width: 3rem; }
  .or-table thead th.num { width: 4.5rem; }
  .or-table.or-bare thead th:nth-child(2) { width: 5rem; }
  .or-table.or-bare thead th:nth-child(3) { width: 3rem; }
}
/* A maker heads its series as a row of the table, its name in ink at the table's size, the whole row its press. */
.or-table .or-maker th { padding: var(--space-3) 0; color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); }
.or-maker-name { display: flex; width: 100%; gap: var(--space-3); }
.or-count { font-weight: var(--weight-regular); }
/* A refused tick's line stands under its row, inside the table. */
.or-held td { padding-top: 0; }
.or-held .pl-fact { margin: 0; }
.or-none { margin: 0; }
/* The source's line keeps the signed table's space under every series, and a wider one under the line that says a search found nothing,
   so it does not read as that line's second sentence. */
.or-results + .pl-credit { margin-top: var(--space-2); }
.vc-chooser .or-results + .pl-credit { margin-top: var(--space-3); }
.or-results:has(> .or-none) + .pl-credit { margin-top: var(--space-5); }
/* Under a vendor's row on the Models in chat page, the two parts' headings are drawn as the tab draws its own, small and quiet. */
.vc-chooser .or-head { margin: var(--space-6) 0 var(--space-3); color: var(--quiet); font-size: var(--size-small); font-weight: var(--weight-strong); line-height: var(--leading-small); }
.vc-chooser .or-part:first-child > .or-head { margin-top: 0; }
/* A vendor reached from the card's Others is outlined where it stands, inside the list's own edge, and the outline fades. */
.vc-landed { outline: 2px solid var(--act); outline-offset: -2px; animation: pl-landed 2.4s ease forwards; }
.pl-list > li.vc-landed:first-child { border-top-left-radius: var(--radius-large); border-top-right-radius: var(--radius-large); }
.pl-list > li.vc-landed:last-child { border-bottom-left-radius: var(--radius-large); border-bottom-right-radius: var(--radius-large); }
@media (prefers-reduced-motion: reduce) { .vc-landed { animation: none; } }

/* ---- The settings window: a window over the page, the viewport less one fixed margin, up to 1024 by 768 ---- */
dialog.sw { width: min(64rem, calc(100vw - 2 * var(--space-6))); height: min(48rem, calc(100vh - 2 * var(--space-6))); max-width: none; max-height: none; padding: 0; border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); color: var(--ink); box-shadow: var(--float-shadow); overflow: hidden; }
dialog.sw[open] { display: flex; }
dialog.sw::backdrop { background: var(--scrim); }

.sw-nav { flex: none; display: flex; flex-direction: column; gap: var(--space-1); width: 12rem; padding: 0 var(--space-4) var(--space-4); border-right: 1px solid var(--frame-line); background: var(--frame); color: var(--frame-ink); font-size: var(--size-small); line-height: var(--leading-small); }
/* The window's name stands level with the close mark. */
.sw-name { display: flex; align-items: center; height: calc(var(--space-8) + 2 * var(--space-4)); margin: 0; padding: 0 var(--space-4); color: var(--frame-quiet); font-size: var(--size-caption); font-weight: var(--weight-regular); line-height: var(--leading-small); }
.sw-nav a { display: flex; align-items: center; min-height: var(--space-8); padding: 0 var(--space-4); border-radius: var(--radius); color: var(--frame-quiet); text-decoration: none; }
.sw-nav a[aria-current="page"] { background: var(--frame-hover); color: var(--frame-ink); }
@media (hover: hover) { .sw-nav a:hover { background: var(--frame-hover); color: var(--frame-ink); } }

.sw-side { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* The close mark has a band of its own above the part that scrolls, so no row ever passes under it. */
.sw-band { flex: none; display: flex; justify-content: flex-end; padding: var(--space-4); border-bottom: 1px solid transparent; }
.sw-side.scrolled .sw-band { border-bottom-color: var(--line); }
.sw-close { display: grid; place-items: center; width: var(--space-8); height: var(--space-8); padding: 0; border: none; background: none; color: var(--quiet); }
.sw-close:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
:where([data-theme="dark"]) .sw-close:hover:not(:disabled) { background: var(--float-hover); }
.sw-pane { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 var(--space-7) var(--space-8); scroll-padding-block: var(--space-6); }
.sw-pane:focus-visible { outline-offset: -2px; }
/* One row grammar: a name and one quiet line at the left, the control at the right, a hairline between rows. */
.sw-group + .sw-group, .sw-foot + .sw-group { margin-top: var(--space-8); }
.sw-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); min-height: var(--space-8); margin-bottom: var(--space-2); }
.sw-head :is(h3, h4) { margin: 0; font-size: var(--size-body); line-height: var(--leading-tight); }
.sw-rows { margin: 0; padding: 0; list-style: none; }
.sw-row { display: flex; align-items: center; gap: var(--space-4) var(--space-7); min-height: calc(var(--space-8) + 2 * var(--space-5)); padding: var(--space-5) 0; }
.sw-rows > * + *, .sw-head + .sw-rows > :first-child, .sw-lots > .sw-rows > :first-child { border-top: 1px solid var(--line); }
.sw-text { flex: 1; min-width: 0; }
.sw-text > p { margin: 0; overflow-wrap: anywhere; }
.sw-label { line-height: var(--leading-small); }
.sw-help { text-wrap: pretty; }
/* Chinese keeps a word whole: a line breaks at its punctuation or at a space, and inside a word only where a clause is longer than its line. */
:lang(zh) :is(dialog.sw, .composer-closed, .status-text) { word-break: keep-all; overflow-wrap: anywhere; }
.sw-ctl { flex: none; display: flex; align-items: center; justify-content: flex-end; gap: var(--space-5); max-width: 62%; }
.sw-btn, .sw a.button { display: inline-flex; align-items: center; justify-content: center; min-height: var(--space-8); white-space: nowrap; }
/* A few values, all in sight: one track, the held one lifted and ringed. */
.sw-seg { display: inline-flex; height: var(--space-8); padding: var(--space-1); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--wash); }
.sw-seg label { position: relative; display: inline-flex; align-items: center; padding: 0 var(--space-5); border-radius: var(--radius-small); color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; cursor: pointer; }
.sw-seg input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: none; opacity: 0; cursor: pointer; }
.sw-seg label:has(:checked) { background: var(--raised); color: var(--ink); box-shadow: 0 0 0 1px var(--edge); }
.sw-seg label:has(:focus-visible) { outline: 2px solid var(--act); outline-offset: 2px; }
@media (hover: hover) { .sw-seg label:hover { color: var(--ink); } }

/* Many values: a menu the page draws, with its chevron. A list longer than eight rows shows half of the ninth, so it is seen to go on. */
.sw-menu { position: relative; }
.sw-menu-button { display: inline-flex; align-items: center; gap: var(--space-3); height: var(--space-8); padding: 0 var(--space-4) 0 var(--space-5); white-space: nowrap; }
.sw-menu-button .icon { flex: none; color: var(--quiet); }
.sw-menu-words { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sw-menu-list { position: absolute; z-index: 2; right: 0; top: calc(100% + var(--space-2)); min-width: 100%; max-height: calc(var(--row) * 8.5 + var(--space-2)); overflow-y: auto; overscroll-behavior: contain; margin: 0; padding: var(--space-2); list-style: none; border: 1px solid var(--float-edge); border-radius: var(--radius-large); background: var(--raised); box-shadow: var(--float-shadow); font-size: var(--size-small); line-height: var(--leading-small); }
.sw-menu-list:focus-visible { outline: none; }
.sw-menu-list [role="option"] { display: flex; align-items: center; gap: var(--space-4); height: var(--row); padding: 0 var(--space-5) 0 var(--space-4); border-radius: var(--radius); white-space: nowrap; cursor: pointer; }
.sw-menu-list [role="option"].at { background: var(--hover); }
:where([data-theme="dark"]) .sw-menu-list [role="option"].at { background: var(--float-hover); }
.sw-menu-list:focus-visible [role="option"].at { outline: 2px solid var(--act); outline-offset: -2px; }
.sw-tick { flex: none; width: 1rem; color: var(--ink); }
.sw-menu-list.sw-spans { min-width: 16rem; max-height: none; overflow: visible; }
.sw-span-grid { display: grid; grid-template-columns: 1fr 1fr; margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line); }
/* A link inside a line of words takes the line's colour and an underline, and a pointer target of its own height. */
.sw-link { position: relative; color: inherit; text-underline-offset: 0.2em; }
.sw-link::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; min-width: var(--space-7); height: var(--space-7); transform: translateY(-50%); }
@media (hover: hover) { .sw-link:hover { color: var(--ink); } }
button.sw-link { padding: 0; border: none; border-radius: var(--radius-small); background: none; font-size: inherit; line-height: inherit; text-decoration: underline; }
button.sw-link:hover:not(:disabled) { background: none; }
.sw-link.meta { color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); }

/* Words for a screen reader alone. */
.sw-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* 用量: a figure with its name over it, and under it the lines that are read with it. */
.sw-top { padding-bottom: var(--space-7); }
.sw-top p { margin: 0; }
.sw-top-line { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4) var(--space-7); min-height: var(--space-8); }
.sw-top .sw-help { margin-top: var(--space-2); }
/* 账单's and 用量's figure opens the section: the next group stands a group's distance under it, the lots the figure sums a block's. */
.sw-top.opens { padding-bottom: 0; }
.sw-top.opens + .sw-group { margin-top: var(--space-8); }
.sw-top.opens + :is(.sw-lot, .sw-lots) { margin-top: var(--space-7); }
/* What the seller must read first stands over everything else: a warning in its colour, an answer to a payment in ink. */
.sw-lead { margin: 0 0 var(--space-4); font-size: var(--size-lead); line-height: var(--leading-tight); text-wrap: pretty; }
.sw-top .sw-lead { margin-bottom: var(--space-4); }
.sw-lead.low { color: var(--money); }
.sw-lead.floor { color: var(--bad); }
.sw-figure { font-size: var(--size-display); line-height: var(--leading-tight); overflow-wrap: anywhere; }
.sw-figure.month { font-size: var(--size-title); }
.sw-figure.unread { color: var(--quiet); font-size: var(--size-lead); }
.sw-amount-cell { min-width: 5rem; text-align: right; white-space: nowrap; }
.sw-more { margin-top: var(--space-4); }
.sw-empty { padding: var(--space-5) 0; }
.sw-empty p { margin: 0; }

/* What leads a money page stands over its first group. */
.sw-leads { margin-bottom: var(--space-6); }
.sw-leads > :last-child { margin-bottom: 0; }
/* 用量: money the account was given. Each lot is a block: its name and what is left on one line, a bar of what it has paid, then the day it ends and the bar's two figures. */
.sw-lot + .sw-lot, .sw-lot + .sw-lots { margin-top: var(--space-7); }
.sw-meter { height: var(--space-3); border-radius: var(--radius-round); background: var(--wash); box-shadow: inset 0 0 0 1px var(--line); overflow: hidden; }
.sw-meter > i { display: block; min-width: var(--space-1); height: 100%; background: var(--money); }
.sw-lot-line { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-1) var(--space-6); margin: var(--space-3) 0 0; }
.sw-lots > .sw-lot-line { margin-top: 0; }
/* The money given, two lots or more: one block under one total, each lot a part of it, ruled as rows are. */
.sw-sublot { padding: var(--space-5) 0; }
.sw-head + .sw-sublot, .sw-sublot + .sw-sublot { border-top: 1px solid var(--line); }
.sw-sublot:last-child { padding-bottom: 0; }
.sw-sublot-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-3); }
.sw-sublot-head h4 { margin: 0; font-size: var(--size-body); font-weight: var(--weight-regular); line-height: var(--leading-tight); }
.sw-lot-more { margin: var(--space-3) 0 0; font-size: var(--size-small); line-height: var(--leading-small); }
/* The period's credit used up, where the next period will start: its name, and under it the day the next credit comes. */
.sw-next > .sw-lot-line { margin-top: 0; }
/* Under a span's total, its own dates. */
.sw-sum .sw-span-range { margin-top: var(--space-1); }
/* A span's total at the left, and at the right the way its days are split, whatever the span: a long span's dates wrap under its total instead. */
.sw-sum { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-6); }
.sw-sum > :first-child { min-width: 0; }
.sw-sum > .sw-seg { flex: none; }
.sw-sum p { margin: 0; }
.sw-sum + .sw-chart { margin-top: var(--space-6); }
.sw-spent > .sw-help { margin: var(--space-2) 0 0; }
/* 用量's spending: a bar per day, drawn as the Plugins page draws a plugin's days. */
.sw-chart { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2) var(--space-4); margin-top: var(--space-4); color: var(--quiet); font-size: var(--size-caption); line-height: var(--leading-small); font-variant-numeric: tabular-nums; }
.sw-yaxis { display: flex; flex-direction: column-reverse; justify-content: space-between; text-align: right; }
.sw-yaxis span { display: flex; align-items: center; justify-content: flex-end; height: 0; }
.sw-plot { position: relative; height: calc(var(--space-8) * 4); }
.sw-gridlines { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; pointer-events: none; }
.sw-gridlines i { display: block; height: 0; border-top: 1px solid var(--line); }
.sw-days, .sw-xaxis { display: grid; }
.sw-days { position: absolute; inset: 0; }
.sw-day { display: flex; align-items: flex-end; justify-content: center; min-width: 0; height: 100%; }
/* The day being read: a band, and a hairline at each side, since in dark the band alone is the window's own colour. */
.sw-day.at { background: var(--hover); box-shadow: inset 1px 0 var(--line), inset -1px 0 var(--line); }
.sw-day:focus-visible { outline-offset: -2px; }
.sw-bar { position: relative; display: flex; flex-direction: column-reverse; gap: 1px; width: 62%; max-width: var(--space-7); min-height: 2px; }
.sw-bar > i { display: block; flex: 1 1 0; min-height: 1px; }
.sw-bar > i:last-child { border-radius: var(--radius-small) var(--radius-small) 0 0; }
.sw-xaxis { position: relative; grid-column: 2; }
.sw-xaxis > span { display: flex; justify-content: center; min-width: 0; white-space: nowrap; }
.sw-xaxis > span.now { color: var(--ink); }
.sw-span-name { color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
.s0 { background: var(--money); }
.s1 { background: var(--money-bar-1); }
.s2 { background: var(--money-bar-2); }
.s3 { background: var(--money-bar-3); }
.s4 { background: repeating-linear-gradient(135deg, var(--money) 0 2px, var(--raised) 2px 4px); }
.s5 { background: repeating-linear-gradient(45deg, var(--money) 0 1px, var(--raised) 1px 4px); box-shadow: inset 0 0 0 1px var(--money); }
.s6 { background: var(--raised); box-shadow: inset 0 0 0 1px var(--money); }
/* A line of the list under the pointer or the keyboard leaves its own series whole and dims the others. */
.sw-chart[data-only="s1"] .sw-bar > :not(.s1), .sw-chart[data-only="s2"] .sw-bar > :not(.s2), .sw-chart[data-only="s3"] .sw-bar > :not(.s3), .sw-chart[data-only="s4"] .sw-bar > :not(.s4),
.sw-chart[data-only="s5"] .sw-bar > :not(.s5), .sw-chart[data-only="s6"] .sw-bar > :not(.s6) { opacity: 0.25; }
/* A day's figures hang under the day's number, below the scale, over no bar; what the keyboard's place hears is the day's own label. */
/* By total no list follows the chart: a row's height is kept under the scale, so a day's one line lies over nothing. */
.sw-chart:last-child { padding-bottom: var(--row); }
.sw-tip[hidden] { display: none; }
.sw-tip { position: absolute; z-index: 1; top: calc(100% + var(--space-2)); display: flex; flex-direction: column; gap: var(--space-1); min-width: 10rem; max-width: 18rem; padding: var(--space-4) var(--space-5); border: 1px solid var(--float-edge); border-radius: var(--radius); background: var(--raised); color: var(--ink); font-size: var(--size-small); line-height: var(--leading-small); box-shadow: var(--float-shadow); pointer-events: none; }
.sw-tip p { display: flex; align-items: center; gap: var(--space-4); margin: 0; }
.sw-tip .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A bar's own minutes, hours, day or month: read whole, on two lines where it needs them. */
.sw-tip .name.when { white-space: normal; }
.sw-tip .sum { margin-top: var(--space-1); padding-top: var(--space-2); border-top: 1px solid var(--line); }
.sw-swatch { flex: none; width: var(--space-5); height: var(--space-5); border-radius: var(--radius-small); }

.sw-lines { margin: var(--space-6) 0 0; padding: 0; list-style: none; }
.sw-lines > li + li { border-top: 1px solid var(--line); }
.sw-line { display: flex; align-items: center; gap: var(--space-5); min-height: calc(var(--space-8) + 2 * var(--space-5)); padding: var(--space-5) 0; color: inherit; text-decoration: none; }
/* A line that opens something: its ground under the pointer reaches past the rows' edges, so the amounts keep one right edge. */
a.sw-line { margin: 0 calc(-1 * var(--space-4)); padding-left: var(--space-4); padding-right: var(--space-4); border-radius: var(--radius); }
a.sw-line:focus-visible { outline-offset: -2px; }
@media (hover: hover) { a.sw-line:hover { background: var(--hover); } :where([data-theme="dark"]) a.sw-line:hover { background: var(--float-hover); } }
.sw-line .sw-label { display: flex; align-items: baseline; gap: var(--space-2); }
.sw-line-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; min-width: 0; overflow: hidden; overflow-wrap: anywhere; }
.sw-line .sw-go { color: var(--quiet); }
.sw-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4) var(--space-7); flex-wrap: wrap; margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--line); }
.sw-foot p { flex: 1 1 12rem; min-width: 0; margin: 0; }
.sw-foot > .sw-btn { margin-left: auto; }
/* ---- 账单, 充值 and 订阅 ---- */
.sw-rule { margin: 0 0 var(--space-4); text-wrap: pretty; }
.sw-ctl:has(> .sw-said.asks) { flex-wrap: wrap-reverse; row-gap: var(--space-2); }
.sw-value { overflow-wrap: anywhere; text-align: right; }
.sw-row.stacked { flex-wrap: wrap; }
.sw-row.stacked > .sw-wide { flex: none; width: 100%; }
.sw-row.roomy { flex-wrap: wrap; }
.sw-row.roomy > .sw-text { flex: 1 1 12rem; }
.sw-row.roomy > .sw-ctl { margin-left: auto; max-width: 100%; }
/* A typed field grows with what it holds, so a name is read back whole: in its row the name keeps its own width and the field's side
   takes the rest. The saved word's place is kept at the field's left, so the field does not move when the word comes and goes. */
.sw-field { field-sizing: content; min-width: 14rem; max-width: 100%; height: var(--space-8); font-size: var(--size-small); line-height: var(--leading-small); }
.sw-row:has(> .sw-ctl > .sw-field) > .sw-text { flex: none; max-width: 38%; }
.sw-row:has(> .sw-ctl > .sw-field) > .sw-ctl { flex: 1 1 0; min-width: 0; max-width: none; }
.sw-ctl:has(> .sw-field) > .sw-said { flex: none; min-width: 3em; text-align: right; }
.sw-note { display: block; width: 100%; min-height: calc(var(--space-9) * 2); padding: var(--space-4); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--raised); font-size: var(--size-small); line-height: var(--leading-small); resize: vertical; }
.sw-field::placeholder, .sw-note::placeholder { color: var(--quiet); opacity: 1; }
.sw-amount { flex: 0 1 auto; display: inline-flex; align-items: center; gap: var(--space-1); min-width: 6rem; max-width: 100%; height: var(--space-8); padding: 0 var(--space-4); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--raised); font-family: var(--font-mono); font-size: var(--size-small); font-variant-numeric: tabular-nums; }
.sw-amount input { flex: 1 1 auto; min-width: 0; height: 100%; padding: 0; border: none; outline: none; background: none; text-align: right; }
.sw-amount:has(:focus-visible) { outline: 2px solid var(--act); outline-offset: 2px; }
.sw-said { color: var(--quiet); font-size: var(--size-small); line-height: var(--leading-small); white-space: nowrap; }
/* A sentence that asks the seller to put something right is read as ink, and may wrap. */
.sw-said.asks { min-width: 0; color: var(--ink); text-align: right; text-wrap: pretty; white-space: normal; }
.sw-switch { min-height: var(--space-8); }
.sw-back { margin: 0 0 var(--space-4); padding-top: var(--space-2); font-size: var(--size-small); line-height: var(--leading-small); }
.sw-back a { display: inline-flex; align-items: center; min-height: var(--space-7); border-radius: var(--radius-small); color: var(--quiet); text-decoration: none; }
@media (hover: hover) { .sw-back a:hover { color: var(--ink); } }
.sw-title { margin: 0 0 var(--space-6); font-size: var(--size-title); line-height: var(--leading-tight); }
.sw-title-line { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: var(--space-2) var(--space-7); margin-bottom: var(--space-6); }
.sw-title-line > .sw-title { margin: 0; }
/* 账单's first row: the membership's state and its line at the left; at the right the figure the account pays with, under its name, and the one act. */
.sw-plan > .sw-ctl { gap: var(--space-6); }
.sw-held { text-align: right; }
.sw-held p { margin: 0; }
.sw-plan > .sw-wide > p { margin: 0; }
.sw-plan > .sw-wide > p + p { margin-top: var(--space-2); }
.sw-label > .pl-tag { margin-left: var(--space-2); }
/* The card form: our step, the provider's fields in its box. */
dialog.confirm.sw-card { width: min(30rem, calc(100vw - 2 * var(--space-6))); }
.sw-card-which { display: flex; flex-direction: column; gap: var(--space-2); }
.sw-card-which label { display: flex; align-items: center; gap: var(--space-4); min-height: var(--space-8); }
.sw-card-which input { margin: 0; }
.sw-card-which + .sw-card-box { margin-top: var(--space-4); }
.sw-card-box { padding: var(--space-6); border: 1px solid var(--edge); border-radius: var(--radius); background: var(--raised); }
.sw-card-bad { margin: var(--space-5) 0 0; color: var(--bad); font-size: var(--size-small); line-height: var(--leading-small); }
/* 通用's switch the browser blocks, 条款 with its way back held at the top, and the invitation sheet: the window without its side. */
.sw-switch[aria-disabled="true"] { cursor: default; }
.sw-switch[aria-disabled="true"] .pl-switch-track { border-color: var(--line); }
.sw-switch[aria-disabled="true"] .pl-switch-knob { background: var(--line); }
.sw-back.stays { position: sticky; top: 0; z-index: 1; margin: 0 calc(-1 * var(--space-7)) var(--space-4); padding: var(--space-2) var(--space-7) var(--space-3); border-bottom: 1px solid transparent; background: var(--raised); }
.sw-side.scrolled:has(.sw-back.stays) .sw-band { border-bottom-color: transparent; }
.sw-side.scrolled .sw-back.stays { border-bottom-color: var(--line); }
.sw-pane:has(.sw-back.stays) { scroll-padding-top: calc(var(--space-7) + var(--space-2) + var(--space-3) + var(--space-4)); }
.sw-terms-list { margin: 0; padding: 0 0 0 var(--space-7); text-wrap: pretty; }
.sw-terms-list > li { padding: var(--space-3) 0; }
.sw-terms-list > li::marker { color: var(--quiet); font-variant-numeric: tabular-nums; }
dialog.sw.sheet { width: min(36rem, calc(100vw - 2 * var(--space-6))); height: fit-content; max-height: calc(100vh - 2 * var(--space-6)); }
dialog.sw.sheet .sw-nav { display: none; }
.sw-gift { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); margin-bottom: var(--space-7); }
.sw-gift-tile { padding: var(--space-6) var(--space-5); border-radius: var(--radius-large); background: var(--wash); text-align: center; }
.sw-gift-tile p { margin: 0; }
.sw-gift-tile .sw-gift-figure { margin: var(--space-2) 0; font-size: var(--size-display); font-weight: var(--weight-strong); line-height: var(--leading-tight); }
.sw-title + .sw-invite-how { margin-top: calc(-1 * var(--space-4)); }
.sw-invite-how { margin: 0 0 var(--space-6); text-wrap: pretty; }
.sw-marks { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-5); }
.sw-mark { flex: none; width: var(--space-7); height: var(--space-5); border-radius: var(--radius-small); background: var(--ink); }
.sw-mark.used { background: none; box-shadow: inset 0 0 0 1px var(--edge); }
.sw-marks > .quiet { margin-left: var(--space-2); }
.sw-link-row { display: flex; align-items: center; gap: var(--space-4); }
.sw-link-field { flex: 1 1 auto; min-width: 0; height: var(--space-8); font-family: var(--font-mono); font-size: var(--size-small); line-height: var(--leading-small); }
.sw-link-row > .sw-btn { flex: none; }
.sw-link-row + .sw-said, .sw-link-ends + .sw-said { min-height: calc(var(--size-small) * var(--leading-small)); margin: var(--space-3) 0 0; text-align: left; }
.sw-link-row + .sw-said.asks, .sw-link-ends + .sw-said.asks { text-align: left; }
.sw-link-ends { margin: var(--space-3) 0 0; text-wrap: pretty; }
.sw-marks ~ .sw-group { margin-top: var(--space-7); }
.sw-friend { overflow-wrap: anywhere; }
/* ---- A half-screen window: the same two sides, less room around the rows ---- */
@media not (min-width: 56rem) {
  .sw-pane { padding-inline: var(--space-6); }
  .sw-back.stays { margin-inline: calc(-1 * var(--space-6)); padding-inline: var(--space-6); }
  .sw-row { gap: var(--space-4) var(--space-6); }
  .sw-ctl:has(> .sw-said.asks) { max-width: 12.5rem; }
  .sw-row.under { flex-wrap: wrap; }
  .sw-row.under > .sw-text { flex: 1 1 100%; }
  .sw-row.under > .sw-ctl { margin-left: auto; max-width: 100%; }
}
/* A phone is not drawn: the sections go across the top so nothing is cut. */
@media not (min-width: 30rem) {
  dialog.sw[open] { flex-direction: column; }
  .sw-nav { flex-direction: row; flex-wrap: wrap; align-items: center; width: auto; padding: var(--space-2) var(--space-4); border-right: none; border-bottom: 1px solid var(--frame-line); }
  .sw-name { height: auto; }
}
