Files
magpie/internal/gui/assets/app.css
T

1197 lines
88 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* magpie — one quiet surface, real logos, controls that read as pop-up buttons. */
:root {
--bg: #f4f4f6;
--card: #ffffff;
--card-2: #f9f9fb; /* expanded editor */
--pill: #f1f1f4;
--pill-hover: #e9e9ee;
--line: #e3e3e8;
--line-2: #ececf0;
--fg: #1c1c21;
--fg-2: #4b4b53;
--muted: #85858d;
--faint: #b9b9c2;
--accent: #4f46e5;
--accent-soft: #eeedfd;
--accent-fg: #ffffff;
--sel: #ecebfb;
--green: #189a58;
--green-soft: #e4f6ec;
--red: #d64545;
--red-soft: #fbe9e9;
--amber: #b45309;
--amber-soft: #fbf0df;
/* an agent magpie set up that no longer goes through it */
--drift: #ce2c31;
--drift-soft: #feebec;
--pop-bg: rgba(255, 255, 255, .94);
--shadow: 0 16px 44px rgba(20, 22, 30, .16), 0 2px 8px rgba(20, 22, 30, .06), 0 0 0 .5px rgba(20, 22, 30, .1);
--font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
--code: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
--logo-invert: 0;
--tk-s: #1a7f45; --tk-k: #7c3aed; --tk-f: #1d4ed8; --tk-n: #b45309; --tk-v: #0e7490; --tk-o: #a21caf; --tk-c: #85858d;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg: #1a1a1e;
--card: #232327;
--card-2: #1f1f23;
--pill: #2d2d33;
--pill-hover: #36363d;
--line: #333339;
--line-2: #2c2c32;
--fg: #ededf1;
--fg-2: #b9b9c1;
--muted: #8b8b94;
--faint: #56565f;
--accent: #a5b4fc;
--accent-soft: #2b2c47;
--accent-fg: #14142a;
--sel: #33345a;
--green: #6fd99b;
--green-soft: #1e3a2b;
--red: #f28b82;
--red-soft: #45272a;
--amber: #f2b544;
--amber-soft: #3f3220;
--drift: #ff9592;
--drift-soft: #3b1219;
--pop-bg: rgba(38, 38, 43, .96);
--shadow: 0 16px 44px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .3), 0 0 0 .5px rgba(255, 255, 255, .1);
--logo-invert: 1;
--tk-s: #98d8a4; --tk-k: #c4b5fd; --tk-f: #93c5fd; --tk-n: #f2b544; --tk-v: #67e8f9; --tk-o: #f0abfc; --tk-c: #8b8b94;
}
}
:root[data-theme="dark"] {
--bg: #1a1a1e; --card: #232327; --card-2: #1f1f23; --pill: #2d2d33; --pill-hover: #36363d;
--line: #333339; --line-2: #2c2c32; --fg: #ededf1; --fg-2: #b9b9c1; --muted: #8b8b94; --faint: #56565f;
--accent: #a5b4fc; --accent-soft: #2b2c47; --accent-fg: #14142a; --sel: #33345a;
--green: #6fd99b; --green-soft: #1e3a2b; --red: #f28b82; --red-soft: #45272a; --amber: #f2b544; --amber-soft: #3f3220;
--drift: #ff9592; --drift-soft: #3b1219;
--pop-bg: rgba(38, 38, 43, .96);
--shadow: 0 16px 44px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .3), 0 0 0 .5px rgba(255, 255, 255, .1);
--logo-invert: 1;
--tk-s: #98d8a4; --tk-k: #c4b5fd; --tk-f: #93c5fd; --tk-n: #f2b544; --tk-v: #67e8f9; --tk-o: #f0abfc; --tk-c: #8b8b94;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
font: 13px/1.4 var(--font);
color: var(--fg);
background: var(--bg);
display: flex;
flex-direction: column;
overflow: hidden;
-webkit-font-smoothing: antialiased;
user-select: none;
-webkit-user-select: none;
cursor: default;
}
/* The tray panel sits on a frosted NSVisualEffectView, so its own paint is thin. */
body.panel { --panel-tint: color-mix(in srgb, var(--bg) 93%, transparent); background: var(--panel-tint); border-radius: 12px; }
/* on the Mac the panel's colour is painted under the page, where it keeps up
with the panel as it grows (see tintPanel) */
body.panel.tinted { background: transparent; }
.tint-probe { display: none; background: var(--panel-tint); }
/* on the frosted panel the surfaces are tints of the backdrop, not flat paint */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) body.panel { --bg: #1b1c20; --card: #25262c; --card-2: #212227; --line: rgba(255, 255, 255, .07); --line-2: rgba(255, 255, 255, .06); --pill: #2e2f36; --pill-hover: #383942; --pill-line: rgba(255, 255, 255, .11); --pill-shadow: 0 1px 2px rgba(0, 0, 0, .28); --muted: #9c9ca6; --faint: #7c7c87; --card-edge: inset 0 0 0 1px rgba(255, 255, 255, .06); }
}
:root[data-theme="dark"] body.panel { --bg: #1b1c20; --card: #25262c; --card-2: #212227; --line: rgba(255, 255, 255, .07); --line-2: rgba(255, 255, 255, .06); --pill: #2e2f36; --pill-hover: #383942; --pill-line: rgba(255, 255, 255, .11); --pill-shadow: 0 1px 2px rgba(0, 0, 0, .28); --muted: #9c9ca6; --faint: #7c7c87; --card-edge: inset 0 0 0 1px rgba(255, 255, 255, .06); }
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) body.panel { --bg: #f2f2f5; --card: #ffffff; --card-2: #f8f8fa; --line: rgba(0, 0, 0, .07); --line-2: rgba(0, 0, 0, .06); --pill: #ffffff; --pill-hover: #f4f4f7; --pill-line: rgba(0, 0, 0, .12); --pill-shadow: 0 1px 1px rgba(0, 0, 0, .06); --faint: #9a9aa3; --card-edge: 0 0 0 1px rgba(0, 0, 0, .05), 0 1px 2px rgba(0, 0, 0, .04); }
}
:root[data-theme="light"] body.panel { --bg: #f2f2f5; --card: #ffffff; --card-2: #f8f8fa; --line: rgba(0, 0, 0, .07); --line-2: rgba(0, 0, 0, .06); --pill: #ffffff; --pill-hover: #f4f4f7; --pill-line: rgba(0, 0, 0, .12); --pill-shadow: 0 1px 1px rgba(0, 0, 0, .06); --faint: #9a9aa3; --card-edge: 0 0 0 1px rgba(0, 0, 0, .05), 0 1px 2px rgba(0, 0, 0, .04); }
button { font: inherit; color: inherit; background: none; border: 0; cursor: default; appearance: none; -webkit-appearance: none; text-align: center; }
button:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
input { font: inherit; color: var(--fg); }
.grow { flex: 1; }
[hidden] { display: none !important; }
code { font: 11.5px var(--code); }
/* ---- brand icons: colour ones are images, mono ones take the text colour --- */
/* a box of its own by default: a mask icon has no size to fall back on, and
one placed where nothing sizes it would otherwise not show at all */
.ic { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 16px; height: 16px; }
.ic img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ic .mask { width: 100%; height: 100%; background: currentColor; -webkit-mask: var(--i) center / contain no-repeat; mask: var(--i) center / contain no-repeat; }
.ic.generic { color: var(--muted); }
/* a routing group's providers, overlapping discs with the first on top */
.ic-stack { display: inline-flex; flex: none; align-items: center; }
.ic-stack .disc { position: relative; width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--card); box-shadow: 0 0 0 1px var(--line); }
.ic-stack .disc + .disc { margin-left: -4px; }
.ic-stack .disc:nth-child(1) { z-index: 3; }
.ic-stack .disc:nth-child(2) { z-index: 2; }
.ic-stack .disc:nth-child(3) { z-index: 1; }
/* the stack sizes its own icons, whatever sizes the icons around it */
.ic-stack .disc > .ic { width: 13px !important; height: 13px !important; }
.ic-stack .more { font-size: 8.5px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.row .field .ic-stack .disc { width: 17px; height: 17px; }
.row .field .ic-stack .disc > .ic { width: 11px !important; height: 11px !important; }
.row .field .ic-stack .disc + .disc { margin-left: -4px; }
.ic.generic svg { width: 100%; height: 100%; }
/* ---- header --------------------------------------------------------------- */
.top { display: flex; align-items: center; gap: 8px; padding: 0 10px 0 14px; height: 46px; flex: none; position: relative; }
body.window.mac .top { padding-left: 96px; height: 50px; padding-top: 2px; } /* the traffic lights centre 25.75pt from the top, not 25 */
body.window.mac .seg { top: calc(50% + 1px); } /* 50% centres in the padding box; the 2px top padding puts the flex row a pixel lower */
.brand { display: flex; align-items: center; gap: 6px; font-weight: 600; letter-spacing: .01em; }
body.window:not(.mac):not(.linux) .brand { display: none; } /* Windows' title bar above already shows the icon and the name */
/* Linux: the header is the title bar, so it closes the window too — round,
as GNOME draws its close button, and set a little apart from the icons */
.icon.winclose { align-self: center; width: 22px; height: 22px; margin-left: 8px; border-radius: 50%; background: var(--pill); color: var(--fg-2); }
.icon.winclose:hover { background: color-mix(in srgb, var(--fg) 12%, transparent); }
/* the magpie flaps, flicks its tail and bobs when the window opens and on
hover. It moves in pieces cut from the logo, and is drawn whole at rest, so
the cuts never show. */
.logo svg { display: block; overflow: visible; }
.logo .parts, .logo.wag .whole { display: none; }
.logo.wag .parts { display: inline; }
.logo .tail { transform-box: view-box; transform-origin: 14px 22px; }
.logo .wing { transform-box: view-box; transform-origin: 30px 19.8px; }
.logo .bird { transform-box: view-box; transform-origin: 26px 38px; }
.logo.wag .tail { animation: tail-flick .9s cubic-bezier(.3, 0, .3, 1); }
.logo.wag .wing { animation: wing-flap .9s cubic-bezier(.3, 0, .3, 1); }
.logo.wag .bird { animation: bird-bob .9s cubic-bezier(.3, 0, .3, 1); }
@keyframes wing-flap {
0%, 100% { transform: none; }
12% { transform: rotate(10deg); }
26% { transform: rotate(-3deg); }
40% { transform: rotate(8deg); }
56% { transform: rotate(-2deg); }
72% { transform: rotate(3deg); }
}
@keyframes tail-flick {
0%, 100% { transform: none; }
18% { transform: rotate(16deg); }
36% { transform: rotate(-7deg); }
54% { transform: rotate(9deg); }
72% { transform: rotate(-3deg); }
86% { transform: rotate(2deg); }
}
@keyframes bird-bob {
0%, 100% { transform: none; }
18% { transform: rotate(-4deg); }
40% { transform: rotate(2deg); }
62% { transform: rotate(-1deg); }
}
.logo { color: var(--fg); display: inline-flex; } /* ink, like the wordmark; the accent blue fought the text in light mode */
.seg {
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
display: inline-flex; padding: 2px; border-radius: 9px;
background: var(--pill);
}
.seg > .thumb { border-radius: 7px; }
body.panel .seg { display: none; }
.seg button { position: relative; z-index: 1; white-space: nowrap; height: 30px; padding: 0 14px; border-radius: 7px; font-size: 13.5px; color: var(--muted); transition: color .18s var(--ease), transform .14s var(--ease); }
.seg button.on { color: var(--fg); }
.seg button:hover:not(.on) { color: var(--fg-2); }
.actions { margin-left: auto; display: flex; gap: 2px; }
.icon {
width: 26px; height: 26px; border-radius: 7px;
display: inline-flex; align-items: center; justify-content: center;
color: var(--muted);
transition: background .12s, color .12s;
}
.icon:hover, .icon.on { background: var(--pill); color: var(--fg); }
/* the icon turns on a layer of its own — painted in place, WebKit leaves
ghosts of each frame behind (#16) — and always finishes its turn */
.icon svg { transform-origin: 50% 50%; backface-visibility: hidden; }
.icon.spin svg { animation: spin .9s linear infinite; will-change: transform; }
/* a newer magpie is ready: a quiet pill before the header's icons */
.update {
align-self: center; display: inline-flex; align-items: center; gap: 4px;
height: 22px; margin-right: 6px; padding: 0 9px 0 7px; border-radius: 999px;
font-size: 11.5px; font-weight: 560; letter-spacing: .005em; white-space: nowrap;
color: var(--accent); background: var(--accent-soft);
box-shadow: inset 0 0 0 .5px color-mix(in srgb, var(--accent) 35%, transparent);
transition: background .15s, color .15s, transform .12s var(--ease), opacity .15s;
animation: update-in .45s var(--ease);
}
.update[hidden] { display: none; }
.update:hover { background: var(--accent); color: var(--accent-fg); }
.update:active { transform: scale(.96); }
.update.busy { pointer-events: none; opacity: .6; }
/* a narrow header (fitTop): the magpie without its name, Update as its arrow,
and at the narrowest the tabs in the row rather than over it */
.top.tight .brand > span:not(.logo), .top.tight .update span { display: none; }
.top.tight .update { width: 22px; padding: 0; justify-content: center; margin-right: 4px; }
body.window .top.cramped .seg { position: relative; left: auto; top: auto; transform: none; margin: 0 auto; } /* relative still: its thumb sits in it, not over the whole header */
.top.cramped .seg button { padding: 0 10px; }
@keyframes update-in { from { opacity: 0; transform: translateY(-3px) scale(.94); } }
@keyframes spin { to { transform: rotate(360deg); } }
/* ---- lists ---------------------------------------------------------------- */
.view { flex: 1; min-height: 0; overflow-y: auto; padding: 0 12px 4px; display: flex; flex-direction: column; animation: view-in .24s var(--ease); }
@keyframes view-in { from { opacity: 0; transform: translateY(5px); } }
body.window .view { padding: 2px 16px 8px; }
.view::-webkit-scrollbar { width: 0; }
/* Windows and Linux draw a classic scrollbar, arrows and all; a thin rounded
thumb instead, like the overlay one macOS shows (left as it is there) */
:where(body:not(.mac)) ::-webkit-scrollbar { width: 10px; height: 10px; background: transparent; }
:where(body:not(.mac)) ::-webkit-scrollbar-thumb { background: var(--faint); border: 3px solid transparent; border-radius: 10px; background-clip: padding-box; }
:where(body:not(.mac)) ::-webkit-scrollbar-thumb:hover { background-color: var(--muted); }
:where(body:not(.mac)) ::-webkit-scrollbar-button, :where(body:not(.mac)) ::-webkit-scrollbar-corner { display: none; background: transparent; }
.list { background: var(--card); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; flex: none; }
body.panel .list { border: 0; border-radius: 10px; box-shadow: var(--card-edge); }
.row { display: flex; align-items: center; gap: 9px; min-height: 40px; padding: 5px 9px 5px 11px; }
body.window .row { min-height: 48px; padding: 7px 12px 7px 14px; gap: 12px; }
.row + .row, .editor + .row, .row + .editor { border-top: 1px solid var(--line-2); }
.row .ic { width: 18px; height: 18px; }
body.window .row .ic { width: 22px; height: 22px; }
.row .name { font-weight: 500; letter-spacing: -.005em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.row .who { min-width: 0; flex: 1 1 auto; }
.row .sub { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.empty-state { padding: 36px 20px; text-align: center; color: var(--muted); }
.empty-state b { display: block; color: var(--fg); font-weight: 500; margin-bottom: 4px; }
/* the last row of the list: the agents nothing is set on, folded away */
.agent-more { display: flex; align-items: center; justify-content: center; gap: 5px; width: 100%; border: 0; border-top: 1px solid var(--line-2); background: none; font: inherit; font-size: 12px; color: var(--muted); padding: 9px; cursor: pointer; transition: color .2s, background-color .2s; }
.agent-more:hover { color: var(--fg); background: var(--card-2); }
.agent-more span { display: inline-flex; }
.agent-more .chev { transition: transform .5s cubic-bezier(.22, 1, .36, 1); }
.agent-more[aria-expanded="true"] .chev { transform: rotate(180deg); }
/* the folded agents unroll like a scroll: the height opens on a long ease-out,
each row settles in a beat after the one above, and the unrolling edge is
soft while it moves. Rolling up is quicker, bottom row first. */
.agent-fold { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .42s cubic-bezier(.4, 0, .2, 1); }
.agent-fold.open { grid-template-rows: 1fr; transition-duration: .62s; transition-timing-function: cubic-bezier(.22, 1, .36, 1); }
.agent-fold-inner { min-height: 0; overflow: hidden; }
.agent-fold-inner > .row:first-child { border-top: 1px solid var(--line-2); }
.agent-fold.moving .agent-fold-inner { -webkit-mask-image: linear-gradient(#000 calc(100% - 32px), transparent); mask-image: linear-gradient(#000 calc(100% - 32px), transparent); }
.agent-fold .row { opacity: 0; transform: translateY(-10px) scale(.985); transform-origin: 50% 0; transition: opacity .22s ease, transform .32s cubic-bezier(.4, 0, .2, 1); transition-delay: calc((var(--n) - 1 - var(--i)) * 22ms); }
.agent-fold.open .row { opacity: 1; transform: none; transition: opacity .42s ease, transform .56s cubic-bezier(.22, 1, .36, 1); transition-delay: calc(70ms + var(--i) * 48ms); }
/* the logo is the row's handle: hovered, it turns into a grip to drag the row
by, and a click opens the row's menu (Move up, Move down, Hide). It takes
no more room than the logo did. */
.ag-handle { display: inline-grid; place-items: center; flex: none; width: 24px; height: 24px; margin: -3px; padding: 0; border: 0; border-radius: 6px; background: none; color: inherit; cursor: grab; touch-action: none; transition: background-color .15s; }
body.window .ag-handle { width: 28px; height: 28px; }
.ag-handle > .ic, .ag-handle > .grip { grid-area: 1 / 1; transition: opacity .15s, transform .2s cubic-bezier(.22, 1, .36, 1); }
.ag-handle > .grip { display: grid; place-items: center; color: var(--muted); opacity: 0; transform: scale(.8); }
.ag-handle:hover, .ag-handle.open, .ag-handle:focus-visible { background: var(--pill); }
.ag-handle:focus-visible { outline: 1.5px solid var(--fg-2); outline-offset: 0; }
.agent-fold .ag-handle { cursor: default; }
#agents > .row .ag-handle:is(:hover, .open, :focus-visible) > .ic, #agents > .row.dragging .ag-handle > .ic { opacity: 0; transform: scale(.8); }
#agents > .row .ag-handle:is(:hover, .open, :focus-visible) > .grip, #agents > .row.dragging .ag-handle > .grip { opacity: 1; transform: none; }
/* one hidden by hand reads as put away, with its way back beside its name */
.agent-fold .row.put-away .ag-handle > .ic, .agent-fold .row.put-away .name { opacity: .6; }
.agent-fold .row.put-away .who { display: flex; align-items: center; gap: 8px; }
/* at the end of the name's column, so it comes up in one place down the rows */
.agent-fold .row .ag-show { margin-left: auto; }
.ag-show { display: inline-flex; align-items: center; gap: 4px; flex: none; height: 22px; padding: 0 8px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); color: var(--fg-2); font: inherit; font-size: 11.5px; cursor: pointer; transition: background-color .15s, color .15s, border-color .15s; }
.ag-show:hover { background: var(--pill); color: var(--fg); }
/* it comes up with the row under the pointer, or the keyboard on it; the
line over the rows already says why they are there */
@media (hover: hover) {
.agent-fold .row .ag-show { opacity: 0; transform: translateX(3px); transition: opacity .15s, transform .2s cubic-bezier(.22, 1, .36, 1), background-color .15s, color .15s; }
.agent-fold .row:is(:hover, :focus-within) .ag-show { opacity: 1; transform: none; }
}
.ag-show:focus-visible { outline: 1.5px solid var(--fg-2); outline-offset: 1px; }
.ag-show svg { color: var(--muted); }
/* an agent whose config was rewritten since magpie set it: a line under
its name saying so, and the button that sets it again */
/* a drifted agent: a coral pill on its name's line — the row keeps its
height and the pickers their columns */
.row.drifted .who { display: flex; align-items: center; gap: 7px; }
.row.drifted .who .name { flex: 0 1 auto; }
.ag-fix { display: inline-flex; align-items: center; gap: 4px; flex: none; height: 20px; padding: 0 8px 0 6px; border: 0; border-radius: 999px; background: var(--drift-soft); color: var(--drift); font: inherit; font-size: 11.5px; font-weight: 500; line-height: 1; cursor: pointer; transition: background-color .15s, color .15s, transform .12s; }
.ag-fix:hover { background: color-mix(in srgb, var(--drift) 16%, var(--drift-soft)); }
.ag-fix:active { transform: scale(.96); }
.ag-fix:focus-visible { outline: 1.5px solid var(--drift); outline-offset: 1px; }
.ag-fix.busy { pointer-events: none; opacity: .7; }
.ag-fix.busy svg { animation: spin .8s linear infinite; }
/* the panel's name column has no room for it: there it is a badge on the
agent's logo, the name and the columns left as every other row's */
body.panel .row.drifted { position: relative; }
body.panel .ag-fix { position: absolute; left: 20px; top: calc(50% + 1px); width: 14px; height: 14px; padding: 0; justify-content: center; background: var(--drift); color: var(--card); box-shadow: 0 0 0 2px var(--card); }
body.panel .ag-fix:hover { background: var(--drift); filter: brightness(1.08); }
body.panel .ag-fix svg { width: 9px; height: 9px; }
body.panel .ag-fix span { display: none; }
.row.drifted .field[data-key="model"] { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--drift) 38%, transparent); }
/* the line over each kind of folded agent: hidden by hand, or nothing set */
.agent-fold-cap { padding: 8px 11px 2px; font-size: 11px; font-weight: 500; color: var(--muted); letter-spacing: .02em; border-top: 1px solid var(--line-2); }
body.window .agent-fold-cap { padding: 10px 14px 3px; }
.agent-fold-cap + .row { border-top: 0; }
.agent-fold .agent-fold-cap { opacity: 0; transition: opacity .22s ease; }
.agent-fold.open .agent-fold-cap { opacity: 1; transition: opacity .42s ease; transition-delay: calc(70ms + var(--i) * 48ms); }
/* while a row is dragged the others slide out of its way */
#agents.sorting { user-select: none; -webkit-user-select: none; }
#agents.sorting > .row { transition: transform .22s cubic-bezier(.22, 1, .36, 1); }
#agents.sorting .ag-handle { cursor: grabbing; }
#agents > .row.dragging, #agents > .row.landing { position: relative; z-index: 2; background: var(--card); box-shadow: 0 6px 18px rgba(20, 22, 30, .12), 0 0 0 1px var(--line); border-radius: 8px; }
#agents > .row.dragging { transition: none; }
#agents > .row.landing { transition: transform .16s cubic-bezier(.22, 1, .36, 1), box-shadow .16s; }
.pop.row-menu { width: auto; min-width: 176px; max-height: none; padding: 4px; border: 1px solid var(--line); display: grid; gap: 1px; }
.row-menu .rm-item { display: flex; align-items: center; gap: 8px; width: 100%; height: 28px; padding: 0 8px; border: 0; border-radius: 7px; background: none; color: var(--fg); font: inherit; font-size: 12.5px; text-align: left; cursor: default; outline: none; }
.row-menu .rm-item svg { flex: none; color: var(--muted); }
.row-menu .rm-item:not(:disabled):is(:hover, :focus) { background: var(--pill); }
.row-menu .rm-item:disabled, .row-menu .rm-item:disabled svg { color: var(--faint); }
.row-menu .rm-name { flex: 1; }
.row-menu .rm-key { margin-left: 14px; font-size: 11px; color: var(--faint); }
.row-menu .rm-sep { height: 1px; margin: 3px 6px; background: var(--line-2); }
/* an agent row: logo, name, then one pop-up button per setting */
/* two columns: the model, then the smaller setting; single controls sit at the end.
Fixed widths keep every chevron on the same vertical line down the list. */
.agent .who { flex: 1 1 auto; }
/* Two fixed columns: the model (or large model) fills the left, the second
setting the right, so every chip and its chevron lines up down the list.
A single control keeps the left column, so the model always sits in the
same place. */
.fields { display: grid; grid-template-columns: minmax(0, 1fr) 124px; gap: 5px; width: 350px; flex: none; margin-left: auto; }
body.panel .fields { width: 272px; grid-template-columns: minmax(0, 1fr) 118px; }
.field {
display: inline-flex; align-items: center; gap: 5px;
max-width: 100%; min-width: 0;
height: 25px; padding: 0 5px 0 8px;
border-radius: 6px;
background: var(--pill);
font-size: 12.5px;
transition: background .12s, box-shadow .12s;
}
/* on the panel a control is a real pop-up button: hairline edge, a breath of shadow */
body.panel .field { height: 24px; font-size: 12px; box-shadow: inset 0 0 0 1px var(--pill-line), var(--pill-shadow); }
body.panel .field:hover { box-shadow: inset 0 0 0 1px var(--pill-line), var(--pill-shadow); }
body.panel .field.open { box-shadow: inset 0 0 0 1px var(--accent), var(--pill-shadow); }
/* the tray panel keeps control-sized pills: a solo control spans both columns
and hugs the right — an economy the narrow panel wants */
/* a field that follows the model unless set: a square in a third column */
#agents.extras .fields { width: 379px; grid-template-columns: minmax(0, 1fr) 124px 24px; }
body.panel #agents.extras .fields { width: 301px; grid-template-columns: minmax(0, 1fr) 118px 24px; }
#agents.extras .field.solo { grid-column: 1 / 3; }
body.window #agents.extras .field.solo { grid-column: 1 / 3; }
.field.extra { grid-column: 3; width: 24px; padding: 0; justify-content: center; position: relative; color: var(--faint); }
.field.extra:hover, .field.extra.open { color: var(--fg-2); }
.field.extra.set { color: var(--fg); }
.field.extra.set::after { content: ""; position: absolute; top: 3px; right: 3px; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.field.main, .field.solo { justify-self: end; }
.field.solo { grid-column: 1 / -1; }
/* in the window the chips fill their column, so every chip and chevron lines
up down the list and the model always sits in the same place */
body.window .field.main, body.window .field.solo { justify-self: stretch; }
body.window .field.solo { grid-column: auto; }
.field:hover, .field.open { background: var(--pill-hover); }
.field.open { box-shadow: inset 0 0 0 1px var(--accent); }
.row .field .ic, body.window .row .field .ic { width: 14px; height: 14px; }
.field .effort-ic { color: var(--fg); }
.field .effort-ic svg { width: 100%; height: 100%; }
.field .k { color: var(--faint); font-size: 11.5px; flex: none; }
.field .v { min-width: 0; flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; font-weight: 500; }
.field .chev { color: var(--faint); display: inline-flex; margin-left: auto; padding-left: 1px; }
.field:hover .chev, .field.open .chev { color: var(--muted); }
.field.flash { animation: flash 1.2s ease-out; }
@keyframes flash { 0%, 35% { box-shadow: inset 0 0 0 1px var(--green); background: var(--green-soft); } 100% {} }
/* ---- usage ---------------------------------------------------------------- */
.usage-head { display: flex; align-items: center; gap: 10px; height: 34px; margin: 4px 0 6px; flex: none; }
.subscription-usage { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 7px; margin-bottom: 8px; flex: none; }
.subscription-card { padding: 10px 12px 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); min-width: 0; }
.subscription-head { display: flex; align-items: center; gap: 7px; margin-bottom: 9px; }
.subscription-head .ic { width: 17px; height: 17px; }
.subscription-head b { font-size: 12.5px; font-weight: 600; }
.subscription-account { display: flex; align-items: baseline; gap: 7px; margin: 0 0 6px; font-size: 11px; color: var(--fg-2); }
.subscription-card.several .quota-windows + .subscription-account,
.subscription-card.several .subscription-error + .subscription-account,
.subscription-card.several .quota-balance + .subscription-account { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--line); }
.subscription-account .user { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subscription-account .plan { margin-left: auto; flex: none; font-size: 10.5px; color: var(--muted); text-transform: capitalize; }
.subscription-head .plan { margin-left: auto; font-size: 10.5px; color: var(--muted); text-transform: capitalize; }
.quota-windows { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 14px; }
/* each window takes two of the grid's rows, its names and its bar, so
when one's count wraps under its name the bars beside it still line up */
.quota-windows .quota { display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 0; }
.quota-windows .quota-track { align-self: start; }
/* a narrow card puts the count under the window's name rather than
squeezing the name a character a line and the count past the edge;
side by side they are at either end, and a count on a line of its own
starts at the left, under the name */
.quota-labels { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 2px 6px; margin-bottom: 4px; font-size: 10.5px; color: var(--muted); }
.quota-labels > span { white-space: nowrap; }
.quota-labels .quota-n { max-width: 100%; padding: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; color: var(--fg-2); font-size: inherit; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.quota-labels .quota-n:hover { color: var(--fg); }
.quota-track { height: 4px; border-radius: 2px; background: var(--pill); overflow: hidden; }
.quota-track i { display: block; height: 100%; border-radius: inherit; background: var(--accent); }
.subscription-error { font-size: 11px; color: var(--faint); }
.quota-balance { display: flex; align-items: baseline; gap: 6px; font-size: 10.5px; color: var(--muted); }
.quota-balance b { margin-left: auto; font-size: 15px; color: var(--fg); font-weight: 600; font-variant-numeric: tabular-nums; }
.skeleton { display: block; border-radius: 5px; background: linear-gradient(90deg, var(--pill) 25%, var(--pill-hover) 45%, var(--pill) 65%); background-size: 240% 100%; animation: skeleton-shift 1.4s ease-in-out infinite; }
@keyframes skeleton-shift { from { background-position: 100% 0; } to { background-position: -100% 0; } }
.sk-cost { width: 72px; height: 15px; }
.skeleton-card { min-height: 78px; display: flex; flex-direction: column; gap: 9px; justify-content: center; }
.sk-title { width: 38%; height: 12px; }
.sk-line { width: 100%; height: 5px; }
.sk-line.short { width: 64%; }
.loading-kpi { min-height: 67px; justify-content: center; gap: 7px; }
.loading-kpi .sk-number { width: 54%; height: 17px; }
.loading-kpi .sk-label { width: 36%; height: 8px; }
#view-usage.loading .opt { cursor: default; }
.usage-cost { display: inline-flex; align-items: baseline; gap: 6px; font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12px; }
.usage-cost b { font-size: 15px; font-weight: 600; color: var(--fg); }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; flex: none; }
.stats.empty { display: block; background: var(--card); }
.stats .none { padding: 18px 16px; color: var(--muted); text-align: center; line-height: 1.5; }
.kpi { background: var(--card); padding: 12px 14px 11px; display: flex; flex-direction: column; min-width: 0; }
.kpi b { font-size: 20px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.kpi span { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); margin-top: 3px; }
.kpi small { font-size: 11px; color: var(--muted); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chart { position: relative; margin-top: 8px; padding: 12px 14px 8px; background: var(--card); border: 1px solid var(--line); border-radius: 12px; flex: none; }
.chart .peak { font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums; text-align: right; margin: 0 0 5px; }
.chart .bars { display: flex; align-items: flex-end; gap: 3px; height: 72px; border-bottom: 1px solid var(--line-2); }
.chart .bar { flex: 1 1 0; min-width: 2px; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; border-radius: 3px 3px 0 0; overflow: hidden; }
.chart .bar:hover { background: var(--pill); }
.chart .bar i { display: block; background: var(--accent); }
.chart .bar i.in { opacity: .38; }
.chart .labels { display: flex; gap: 3px; margin-top: 5px; font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chart .labels span { flex: 1 1 0; min-width: 0; white-space: nowrap; overflow: visible; }
.chart .labels span:last-child { text-align: right; }
.row.stat .who { flex: 0 0 180px; }
.row.stat .share { flex: 1 1 auto; height: 4px; border-radius: 2px; background: var(--pill); overflow: hidden; margin: 0 6px; }
.row.stat .share i { display: block; height: 100%; border-radius: 2px; background: var(--accent); opacity: .7; }
.row.stat .num { display: flex; flex-direction: column; align-items: flex-end; flex: none; min-width: 64px; font-variant-numeric: tabular-nums; }
.row.stat .num b { font-weight: 600; }
.row.stat .num small { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.row.stat .cost { flex: none; min-width: 58px; text-align: right; color: var(--green); font-variant-numeric: tabular-nums; font-size: 12px; }
.usage-note { padding: 10px 4px 2px; font-size: 11px; color: var(--faint); user-select: text; -webkit-user-select: text; }
.usage-pane { display: flex; flex-direction: column; flex: none; }
.usage-pane[hidden] { display: none; }
/* ---- sessions, a segment of usage ------------------------------------------ */
.sess-tools { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; flex: none; }
.sess-tools .grow { flex: 1; }
.sess-filter { width: 220px; max-width: 100%; height: 26px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 12px; outline: none; }
.sess-filter:focus { border-color: var(--accent); }
.sess-list { margin-top: 8px; }
.sess-sk { flex-direction: column; align-items: stretch; justify-content: center; gap: 7px; min-height: 48px; }
.sess-item + .sess-item { border-top: 1px solid var(--line-2); }
.sess-item.open { background: color-mix(in srgb, var(--pill) 45%, transparent); }
.row.sess { cursor: default; min-height: 46px; }
.row.sess:hover { background: var(--pill); }
.row.sess .num { display: flex; flex-direction: column; align-items: flex-end; flex: none; min-width: 64px; font-variant-numeric: tabular-nums; }
.row.sess .num b { font-weight: 600; }
.row.sess .num small { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.row.sess .cost { flex: none; min-width: 58px; text-align: right; color: var(--green); font-variant-numeric: tabular-nums; font-size: 12px; }
.row.sess .cost.none { color: var(--faint); }
.sess-resume { flex: none; height: 24px; padding: 0 10px; border-radius: 7px; border: 0; background: var(--pill); color: var(--fg); font-size: 11.5px; font-weight: 500; white-space: nowrap; }
.sess-resume:hover { background: var(--pill-hover); }
.sess-resume.done { background: var(--green-soft); color: var(--green); }
.sess-term { flex: none; }
.sess-detail { display: flex; flex-direction: column; gap: 5px; padding: 2px 12px 11px 38px; font-size: 11.5px; user-select: text; -webkit-user-select: text; }
.sess-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sess-line .k { flex: 0 0 64px; color: var(--muted); }
.sess-line .v { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg-2); }
.sess-line code { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--code); font-size: 11px; padding: 2px 6px; border-radius: 5px; background: var(--pill); }
.sess-line .copy { flex: none; }
.sess-models { display: grid; grid-template-columns: minmax(0, auto) 1fr auto; gap: 3px 12px; margin: 3px 0 2px 72px; font-variant-numeric: tabular-nums; }
.sess-models .model { font-family: var(--code); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sess-models .n { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sess-models .c { text-align: right; color: var(--green); }
.sess-models .c.none { color: var(--faint); }
@media (max-width: 560px) {
.row.sess .num small { display: none; }
.sess-filter { width: 150px; }
.sess-models { margin-left: 0; grid-template-columns: minmax(0, 1fr) auto; }
.sess-models .n { display: none; }
.sess-detail { padding-left: 12px; }
}
/* ---- the panel's usage, a line per account ------------------------------- */
.panel-quota { flex: none; padding: 6px 4px 2px; }
.pq-head { display: inline-flex; align-items: center; gap: 4px; padding: 2px 0; background: none; border: 0; color: var(--muted); cursor: default; }
.pq-head .chev { display: inline-flex; transform: rotate(-90deg); transition: transform .2s; }
.pq-head.open .chev { transform: none; }
.pq-list { display: flex; flex-direction: column; gap: 1px; padding-top: 4px; }
.pq-row { display: flex; align-items: center; gap: 8px; min-height: 24px; font-size: 12px; }
.pq-row .ic { flex: none; }
.pq-who { flex: 1 1 0; min-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg-2); }
.pq-ws { flex: 0 1 auto; min-width: 0; display: flex; align-items: center; gap: 14px; font-size: 10.5px; color: var(--muted); }
.pq-w { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; min-width: 0; }
.pq-n { max-width: 84px; overflow: hidden; text-overflow: ellipsis; }
.pq-track { width: 44px; height: 4px; border-radius: 2px; background: var(--pill); overflow: hidden; }
.pq-track i { display: block; height: 100%; border-radius: inherit; background: var(--fg-2); }
.pq-w b, .pq-ws > b { min-width: 28px; text-align: right; color: var(--fg-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.pq-w.full b { color: var(--fg); }
.pq-w.full .pq-track i { background: var(--fg); }
.pq-none { color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pq-row .skeleton.sk-aq { width: 110px; height: 8px; border-radius: 4px; }
#view-agents.loading .panel-quota { visibility: hidden; }
/* ---- profiles ------------------------------------------------------------- */
.profiles { display: flex; align-items: center; gap: 10px; padding: 10px 4px 2px; min-height: 36px; flex: none; }
.profiles .label { flex: none; }
.profiles .chips { flex: 1 1 0; min-width: 0; padding: 0; min-height: 0; }
.profiles #save { margin-left: auto; flex: none; }
/* switching profile is what the panel is opened for: a target to hit, not a tag */
.profiles .chips { gap: 8px; }
.profiles .chip { height: 30px; padding: 0 6px 0 13px; font-size: 13px; }
.profiles .chip .x { width: 20px; height: 20px; font-size: 13px; }
.profiles .chips .hint { line-height: 30px; }
.row-head { display: flex; align-items: center; height: 26px; }
.label { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.text { font-size: 12px; color: var(--muted); padding: 3px 7px; border-radius: 6px; transition: background .12s, color .12s; white-space: nowrap; }
.text:hover { color: var(--fg); background: var(--pill); }
.text.action { height: 27px; padding: 0 10px; border: 1px solid var(--line); background: var(--card); color: var(--fg-2); box-shadow: 0 1px 1px rgba(0, 0, 0, .04); display: inline-flex; align-items: center; justify-content: center; }
.text.action:hover { border-color: var(--muted); background: var(--card-2); color: var(--fg); }
.text.primary { color: var(--accent-fg); background: var(--accent); font-weight: 500; }
.text.primary:hover { filter: brightness(1.08); }
.text.danger:hover { color: var(--red); background: var(--red-soft); }
.chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0 6px; min-height: 12px; }
.chip {
display: inline-flex; align-items: center; gap: 2px;
height: 25px; padding: 0 5px 0 10px;
border-radius: 999px;
border: 1px solid var(--line);
background: var(--card);
font-size: 12px;
transition: border-color .12s, background .12s, color .12s;
}
.chip:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.chip .lib { width: 5px; height: 5px; margin: 0 2px 0 4px; border-radius: 50%; background: var(--accent); opacity: .7; flex: none; }
.chip .x { width: 16px; height: 16px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; line-height: 1; opacity: 0; transition: opacity .12s; }
.chip:hover .x { opacity: .6; }
.chip .x:hover { opacity: 1; background: rgba(127, 127, 127, .2); }
.chip-input {
height: 25px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--accent);
background: var(--card); outline: none; width: 140px; font-size: 12px;
}
.chips .hint { font-size: 11.5px; color: var(--muted); line-height: 25px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ---- footer --------------------------------------------------------------- */
.foot { display: flex; align-items: center; gap: 2px; padding: 0 8px 6px 14px; min-height: 28px; flex: none; }
body.window .foot { padding-left: 18px; }
.status { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: opacity .3s; }
.status.ok { color: var(--green); }
.status.err { color: var(--red); }
.status.warn { color: var(--amber); }
/* ---- picker popover ------------------------------------------------------- */
.pop {
position: fixed; z-index: 30; /* above the modal (20): a picker opened from the provider editor must show over it */
width: 320px; max-height: 340px;
display: flex; flex-direction: column;
background: var(--pop-bg);
-webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
border-radius: 11px;
box-shadow: var(--shadow);
overflow: hidden;
transform-origin: top left;
animation: pop .14s cubic-bezier(.2, .8, .3, 1);
}
.pop.up { transform-origin: bottom left; }
@keyframes pop { from { opacity: 0; transform: scale(.97) translateY(-3px); } }
.pop .search { display: flex; align-items: center; gap: 8px; padding: 0 12px; border-bottom: 1px solid var(--line-2); color: var(--faint); }
.pop input { flex: 1; background: none; border: 0; outline: none; height: 36px; font-size: 13px; }
.pop input::placeholder { color: var(--faint); }
.picker-body { display: flex; min-height: 0; flex: 1 1 auto; }
#pickerRail[hidden] { display: none; }
#pickerRail { position: relative; width: 43px; padding: 6px 5px; border-right: 1px solid var(--line-2); display: flex; flex-direction: column; align-items: center; gap: 3px; flex: none; overflow-y: auto; overflow-x: hidden; scrollbar-width: none; }
/* it draws its own thumb (.rail-thumb) */
#pickerRail::-webkit-scrollbar { width: 0; height: 0; }
.rail-thumb { position: absolute; z-index: 0; top: 0; left: 5px; width: 31px; height: 31px; border-radius: 8px; opacity: 0; background: var(--sel); box-shadow: inset 0 0 0 1px var(--line-2), 0 1px 2px rgba(0, 0, 0, .06); pointer-events: none; transition: transform 260ms cubic-bezier(.22, 1, .36, 1), opacity 100ms ease-out; will-change: transform; }
.rail-item { position: relative; z-index: 1; width: 31px; height: 31px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted); flex: none; transition: color 150ms ease-out, transform 150ms cubic-bezier(.25, 1, .5, 1); }
.rail-item:hover { color: var(--fg); background: color-mix(in srgb, var(--pill) 68%, transparent); }
.rail-item:active { transform: scale(.94); }
.rail-item.on { color: var(--fg); background: transparent; }
.rail-item .ic { width: 16px; height: 16px; transition: transform 220ms cubic-bezier(.22, 1, .36, 1); }
.rail-item.on .ic { transform: scale(1.04); }
.rail-sep { width: 24px; height: 1px; margin: 2px 0; background: var(--line-2); flex: none; }
.pop ul { list-style: none; overflow-y: auto; padding: 5px; min-width: 0; flex: 1 1 auto; contain: paint; }
.pop li {
display: flex; align-items: center; gap: 9px;
height: 30px; padding: 0 8px; border-radius: 7px;
white-space: nowrap; font-size: 12.5px;
}
.pop li .ic { width: 16px; height: 16px; }
.pop li .option-words { display: flex; align-items: center; min-width: 0; flex: 1 1 auto; gap: 9px; }
.pop li .v { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.pop li .n { flex: 1 1 0; min-width: 0; font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.pop li .favorite { display: none; align-items: center; justify-content: center; color: var(--faint); width: 24px; height: 24px; border-radius: 6px; flex: none; }
.pop li:hover .favorite, .pop li .favorite.on { display: inline-flex; }
.pop li .favorite:hover { color: var(--amber); background: var(--pill-hover); }
.pop li .favorite.on { color: var(--amber); }
.pop.model-picker { max-height: 420px; border: 1px solid var(--line); }
.pop.model-picker .search { min-height: 39px; }
.pop.model-picker .search input { height: 38px; }
.pop.model-picker li:not(.group) { height: 34px; padding: 0 8px; }
.pop.model-picker li .option-words { flex-direction: row; align-items: baseline; justify-content: flex-start; gap: 9px; }
.pop.model-picker li .v { max-width: 62%; font-size: 12.5px; line-height: 18px; flex: 0 1 auto; }
.pop.model-picker li .n { width: auto; flex: 1 1 0; font-size: 10.5px; line-height: 18px; }
.pop.model-picker li.group { height: 24px; padding-top: 7px; }
/* the effort slider: a thin track filled in the text colour up to the
level, a dot at every stop, the ends named beneath it */
.pop.effort-picker { max-height: none; border-radius: 12px; }
.effort-control { padding: 12px 14px 11px; }
.effort-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 8px; font-size: 11.5px; }
.effort-head span { color: var(--muted); }
.effort-head b { margin-left: auto; color: var(--fg); font-size: 12.5px; font-weight: 600; }
.effort-track { --fill: 0%; position: relative; height: 20px; }
.effort-ticks { position: absolute; z-index: 3; left: 8px; right: 8px; top: 8.5px; height: 3px; pointer-events: none; }
.effort-ticks i { position: absolute; left: calc(var(--at) * 100%); width: 3px; height: 3px; margin-left: -1.5px; border-radius: 50%; background: var(--faint); transition: background-color 120ms ease-out; }
.effort-ticks i.on { background: var(--card); opacity: .7; }
.effort-ticks i.cur { opacity: 0; }
.effort-control input[type="range"] { --fill: 0%; position: relative; z-index: 2; display: block; width: 100%; height: 20px; margin: 0; padding: 0; appearance: none; -webkit-appearance: none; background: transparent; outline: none; cursor: pointer; }
.effort-control input[type="range"]::-webkit-slider-runnable-track { height: 4px; border-radius: 999px; background: linear-gradient(90deg, var(--fg) 0 var(--fill), var(--line) var(--fill) 100%); }
.effort-control input[type="range"]::-webkit-slider-thumb { width: 16px; height: 16px; margin-top: -6px; border: 0; border-radius: 50%; appearance: none; -webkit-appearance: none; background: #fff; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .18), 0 1px 3px rgba(0, 0, 0, .22); transition: transform 140ms cubic-bezier(.25, 1, .5, 1); }
.effort-control input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.08); }
.effort-control input[type="range"]:active::-webkit-slider-thumb { transform: scale(.94); }
.effort-control input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 .5px rgba(0, 0, 0, .18), 0 1px 3px rgba(0, 0, 0, .22), 0 0 0 3px var(--accent-soft); }
.effort-ends { display: flex; justify-content: space-between; margin-top: 5px; font-size: 10.5px; color: var(--muted); opacity: .8; }
.pop li.sel { background: var(--sel); }
.pop li .check { color: var(--accent); display: none; margin-left: auto; flex: none; }
.pop li.cur .check { display: inline-flex; }
.pop li.group { height: 22px; padding: 6px 8px 0; font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); pointer-events: none; }
.pop li.group:not(:first-child) { margin-top: 2px; }
.pop li.reset { margin-bottom: 3px; }
.pop li.reset .v { color: var(--fg); }
.pop li.reset .ic { opacity: .75; }
.pop li.custom .v { color: var(--fg); }
.pop li.custom .n { color: var(--muted); }
.pop .none { padding: 10px 12px; color: var(--muted); font-size: 12px; white-space: normal; line-height: 1.45; }
.pop.keying .search { border-bottom-color: var(--accent); color: var(--accent); }
.pop .none b { color: var(--fg); font-weight: 500; }
/* ---- gateway page --------------------------------------------------------- */
/* Loading keeps the final geometry in place, so entering Gateway feels calm
even while provider discovery and account checks are still running. */
.pv-sk-row { min-height: 45px; }
.pv-sk-icon { width: 18px; height: 18px; border-radius: 5px; flex: none; }
.pv-sk-who { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
.pv-sk-name { width: 112px; height: 11px; }
.pv-sk-sub { width: min(260px, 64%); height: 8px; }
.pv-sk-key { width: 64px; height: 18px; border-radius: 9px; flex: none; }
#view-providers.loading .after-list { visibility: hidden; }
/* the agents' rows while they are first read: the icon, the name and the two setting columns */
.ag-sk-icon { width: 18px; height: 18px; border-radius: 5px; flex: none; }
body.window .ag-sk-icon { width: 22px; height: 22px; border-radius: 6px; }
.ag-sk-name { width: 92px; height: 11px; }
.ag-sk-field { height: 25px; border-radius: 6px; }
.ag-sk-row:nth-child(2n) .ag-sk-name { width: 64px; }
.ag-sk-row:nth-child(3n) .ag-sk-name { width: 78px; }
#view-agents.loading .profiles { visibility: hidden; }
.gw-sk-dot { width: 8px; height: 8px; margin: 0 7px; border-radius: 50%; flex: none; }
.gw-sk-who { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
.gw-sk-title { width: 118px; height: 12px; }
.gw-sk-sub { width: min(330px, 72%); height: 8px; }
.gw-sk-url { width: 154px; height: 24px; border-radius: 6px; flex: none; }
.gw-sk-label { width: 46px; height: 8px; align-self: center; justify-self: end; }
.gw-sk-field { min-height: 30px; display: flex; flex-direction: column; justify-content: center; gap: 5px; }
.gw-sk-field .skeleton { width: min(310px, 72%); height: 10px; }
.gw-sk-field .skeleton.short { width: min(210px, 48%); height: 7px; }
.gw-sk-row { pointer-events: none; }
.gw-sk-model { width: 190px; height: 10px; }
.gw-sk-provider { width: 82px; height: 9px; }
.gw-sk-call { cursor: default; pointer-events: none; }
.gw-sk-call .skeleton { height: 8px; }
.gw-sk-call .time { width: 54px; }
.gw-sk-call .agent { width: 62px; }
.gw-sk-call .model { width: 150px; }
.gw-sk-call .result { width: 68px; }
/* the status card: a dot where the logo would be, the URL as a pill */
.gwcard { margin: 4px 0 2px; }
.gw .dot { width: 8px; height: 8px; margin: 0 7px; border-radius: 50%; background: var(--amber); flex: none; box-shadow: 0 0 0 3px var(--amber-soft); }
.gw .dot.on { background: var(--green); box-shadow: 0 0 0 3px var(--green-soft); }
.gw .who { flex: 1 1 auto; }
.gw .name .state { margin-left: 8px; font-size: 11px; font-weight: 500; color: var(--green); }
.gw .dot:not(.on) ~ .who .state { color: var(--amber); }
.gw .url { display: inline-flex; align-items: center; height: 24px; padding: 0 8px; border-radius: 6px; background: var(--pill); box-shadow: inset 0 0 0 1px var(--line-2); flex: none; transition: background .12s, box-shadow .12s; }
.gw .url:hover { background: var(--pill-hover); box-shadow: inset 0 0 0 1px var(--line); }
.gw .url code { color: var(--fg-2); font-size: 11px; }
.gw .url:hover code { color: var(--fg); }
#view-gateway .row-head, #view-usage .row-head { margin: 14px 0 6px; padding: 0 2px; }
#view-usage .row-head.quota-head { margin: 6px 0 6px; }
#view-gateway .row-head .note { font-size: 11px; color: var(--faint); }
/* the connect card: label column, then the value with a copy button */
.connect { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 10px 14px; align-items: start; padding: 12px 14px 14px; }
.connect > div { min-width: 0; }
.connect label { font-size: 12px; color: var(--muted); text-align: right; padding-top: 4px; }
.connect .hint { font-size: 11px; color: var(--faint); margin-top: 4px; line-height: 1.4; }
.connect .val { display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 4px 0 9px; border-radius: 7px; background: var(--pill); box-shadow: inset 0 0 0 1px var(--line-2); max-width: 100%; }
.connect .val code { font-size: 12px; color: var(--fg); user-select: text; -webkit-user-select: text; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.connect .segs { margin-top: -1px; }
.connect .stack { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.copy { width: 22px; height: 22px; border-radius: 5px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted); flex: none; transition: background .12s, color .12s; }
.copy:hover { background: var(--pill-hover); color: var(--fg); }
.copy.done { color: var(--green); background: var(--green-soft); animation: copy-pop .36s var(--ease); }
@keyframes copy-pop { 0% { transform: scale(.55); } 55% { transform: scale(1.16); } 100% { transform: scale(1); } }
.snip-wrap { position: relative; min-width: 0; }
.snip { margin: 0; padding: 10px 40px 10px 12px; border-radius: 9px; background: var(--card); border: 1px solid var(--line); overflow-x: auto; line-height: 1.55; }
.snip code { font-size: 11.5px; color: var(--fg); white-space: pre; user-select: text; -webkit-user-select: text; }
.snip-wrap > .copy { position: absolute; top: 6px; right: 6px; background: var(--card); }
.snip-wrap > .copy:hover { background: var(--pill-hover); }
.snip-wrap > .copy.done { background: var(--green-soft); }
.tk-s { color: var(--tk-s); } .tk-k { color: var(--tk-k); } .tk-f { color: var(--tk-f); } .tk-n { color: var(--tk-n); }
.tk-v { color: var(--tk-v); } .tk-o { color: var(--tk-o); } .tk-c { color: var(--tk-c); font-style: italic; }
.snip::-webkit-scrollbar { height: 0; }
/* the model list: id first, the human name and vendor under it */
.row.model { min-height: 40px; cursor: default; }
.row.model:hover { background: var(--card-2); }
.row.model.selected { background: var(--sel); }
.row.model .name { font: 12px var(--code); }
.row.model .copy { opacity: 0; }
.row.model:hover .copy, .row.model.selected .copy { opacity: 1; }
.row.model .copy.done { opacity: 1; }
/* recent calls */
.activity { padding: 5px 8px 6px; font-size: 11.5px; }
.activity .none { padding: 8px 6px; color: var(--muted); line-height: 1.45; }
.call-item + .call-item { border-top: 1px solid transparent; }
.call-item.open { margin: 2px 0 5px; border-radius: 8px; background: var(--card-2); box-shadow: inset 0 0 0 1px var(--line-2); overflow: hidden; }
.call { display: flex; align-items: center; gap: 10px; height: 24px; padding: 0 6px; border-radius: 6px; white-space: nowrap; cursor: pointer; outline: none; }
.call:hover { background: var(--pill); }
.call:focus-visible { box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 2px var(--accent-soft); }
.call-chev { width: 10px; height: 16px; display: inline-flex; align-items: center; justify-content: center; color: var(--faint); flex: none; transition: transform .15s ease-out, color .12s; }
.call:hover .call-chev { color: var(--muted); }
.call-item.open .call-chev { transform: rotate(90deg); }
.call .when { color: var(--faint); font-variant-numeric: tabular-nums; }
.call .a { color: var(--fg-2); flex: 0 0 auto; max-width: 90px; overflow: hidden; text-overflow: ellipsis; }
.call .m { font-family: var(--code); font-size: 11px; color: var(--fg); overflow: hidden; text-overflow: ellipsis; }
.call .p { color: var(--muted); }
.call .st { color: var(--green); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; max-width: 55%; }
.call-item.bad .st { color: var(--red); }
.call-details { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px; border-top: 1px solid var(--line-2); background: var(--line-2); }
.call-body { min-width: 0; background: var(--card); }
.call-body-head { height: 29px; padding: 0 8px 0 10px; display: flex; align-items: center; gap: 7px; color: var(--muted); }
.call-body-label { font-size: 10.5px; font-weight: 600; letter-spacing: .015em; }
.call-body-truncated { font-size: 9.5px; color: var(--amber); }
.call-body .copy { width: 20px; height: 20px; }
.call-body pre { margin: 0; padding: 9px 10px 11px; min-height: 54px; max-height: 280px; overflow: auto; border-top: 1px solid var(--line-2); background: var(--code-bg, var(--card-2)); }
.call-body code { display: block; font: 10.5px/1.5 var(--code); color: var(--fg-2); white-space: pre-wrap; overflow-wrap: anywhere; user-select: text; -webkit-user-select: text; tab-size: 2; }
.call-body code.empty { color: var(--faint); font-family: var(--font); }
@media (max-width: 760px) { .call-details { grid-template-columns: 1fr; } }
/* ---- providers page ------------------------------------------------------- */
.provider .chev { color: var(--faint); display: inline-flex; transition: transform .15s; }
.provider.selected .chev { transform: rotate(90deg); }
/* a provider row: logo, name, the agents on it, key status */
.provider .who { flex: 1 1 auto; }
.provider .name .badge { margin-left: 6px; }
.badge { font-size: 9.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; padding: 1px 5px; border-radius: 4px; background: var(--amber-soft); color: var(--amber); vertical-align: 1px; }
.provider.selected { background: var(--card-2); }
.uses { display: flex; align-items: center; gap: 4px; margin-left: auto; flex: none; }
.use {
width: 26px; height: 26px; border-radius: 8px;
display: inline-flex; align-items: center; justify-content: center;
background: var(--pill); box-shadow: inset 0 0 0 1px var(--line-2);
transition: background .12s, box-shadow .12s, color .12s;
}
.use .ic { width: 16px; height: 16px; }
.use:hover, .use.open { background: var(--pill-hover); box-shadow: inset 0 0 0 1px var(--line); }
.use.open { box-shadow: inset 0 0 0 1px var(--accent); }
.use.add { background: none; box-shadow: none; border: 1px dashed var(--line); color: var(--faint); }
.use.add:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.key { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: 6px; font: 11px var(--code); color: var(--muted); white-space: nowrap; flex: none; margin-left: 4px; min-width: 108px; font-variant-numeric: tabular-nums; }
.key::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--green); }
.key.free { font-family: var(--font); color: var(--faint); }
.key.free::before { background: var(--faint); }
.key.none { font-family: var(--font); color: var(--amber); background: var(--amber-soft); }
.key.none::before { background: var(--amber); }
.key.acct { font-family: var(--font); }
.acct { display: flex; align-items: center; gap: 8px; min-height: 26px; font-size: 12.5px; }
.acct .n { font-weight: 500; }
.acct .plan { color: var(--muted); font-size: 11.5px; padding: 1px 6px; border-radius: 5px; background: var(--pill-hover); }
/* a subscription's accounts: the one in use first, a way to add another */
.accts { display: grid; border: 1px solid var(--line); border-radius: 10px; background: var(--card); overflow: hidden; }
.acc { display: flex; align-items: center; gap: 9px; min-height: 38px; padding: 5px 8px 5px 11px; font-size: 12.5px; text-align: left; }
.acc + .acc, .accts .signing { border-top: 1px solid var(--line-2); }
.acc .n { font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc .plan { color: var(--muted); font-size: 11px; padding: 1px 6px; border-radius: 5px; background: var(--pill); white-space: nowrap; }
.acc .grow { flex: 1; }
.acc .dot { width: 16px; height: 16px; flex: none; border-radius: 50%; display: grid; place-items: center; box-shadow: inset 0 0 0 1.5px var(--faint); color: var(--muted); }
.acc.in-use .dot { background: var(--fg); box-shadow: none; color: var(--card); }
.acc .using { font-size: 11px; color: var(--fg-2); padding: 2px 8px; border-radius: 999px; box-shadow: inset 0 0 0 1px var(--line); }
.acc .text.quiet { color: var(--muted); opacity: 0; transition: opacity .15s; }
.acc:hover .text.quiet, .acc .text.quiet:focus-visible { opacity: 1; }
.acc.new { animation: sub-in .5s cubic-bezier(.2, .8, .2, 1); }
.acc.new .dot { animation: copy-pop .45s cubic-bezier(.2, .8, .2, 1); }
@keyframes sub-in { from { opacity: 0; transform: translateY(-4px); background: var(--pill-hover); } }
.acc.add { width: 100%; color: var(--fg-2); background: none; border: 0 solid var(--line-2); cursor: default; }
.acc + .acc.add { border-top-width: 1px; }
.acc.add .dot { box-shadow: inset 0 0 0 1.5px var(--faint); border-radius: 50%; }
.acc.add .n { font-weight: 450; }
.acc.add:hover { background: var(--card-2); color: var(--fg); }
.acc.add:hover .dot { box-shadow: inset 0 0 0 1.5px var(--fg); color: var(--fg); }
.acc .rename { font: inherit; font-weight: 500; color: inherit; background: none; border: 0; padding: 0; cursor: text; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc .rename:hover { text-decoration: underline dotted var(--faint); text-underline-offset: 3px; }
.acc .dot.tick { padding: 0; border: 0; background: none; cursor: default; transition: background .15s, box-shadow .15s; }
.acc .dot.tick:hover { box-shadow: inset 0 0 0 1.5px var(--fg); }
.acc.in-use .dot.tick { background: var(--fg); }
.acc.off .n, .acc.off .plan { opacity: .55; }
.acc .rename.mono { font-family: var(--code); font-size: 11.5px; font-weight: 450; }
.acc .rename-in { height: 24px; padding: 0 7px; font-size: 12.5px; max-width: 220px; }
.acc .plan.mono { font-family: var(--code); font-size: 10.5px; }
.acc.adding { display: grid; gap: 8px; padding: 10px 10px 8px 11px; background: var(--card-2); }
.acc.adding .kf { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 6px; }
.acc.adding .kb { display: flex; align-items: center; gap: 4px; }
.acc.adding .kb .grow { flex: 1; }
.acc + .acc.adding { border-top: 1px solid var(--line-2); }
@media (max-width: 520px) { .acc.adding .kf { grid-template-columns: 1fr; } }
.acc .proto { flex: none; display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 5px 0 7px; font: inherit; font-size: 11px; color: var(--muted); border: 0; border-radius: 5px; background: var(--pill); white-space: nowrap; cursor: default; transition: opacity .15s, background .12s, color .12s; }
.acc .proto svg { opacity: .7; transition: transform .15s var(--ease); }
.acc .proto.open svg { transform: rotate(180deg); }
.acc .proto:not(.set) { opacity: 0; background: none; box-shadow: inset 0 0 0 1px var(--line); }
.acc:hover .proto, .acc .proto:focus-visible, .acc .proto.open, .acc.adding .proto { opacity: 1; }
.acc .proto.set { color: var(--fg-2); }
.acc .proto:hover, .acc .proto.open { color: var(--fg); background: var(--pill-hover); }
.acc .n, .acc .rename { flex: 0 1 auto; }
.acc .plan { flex: none; }
/* the Settings row's picker: the key row's badge, always shown */
.row.pref .proto.pick { flex: none; margin-left: auto; display: inline-flex; align-items: center; gap: 3px; height: 24px; padding: 0 6px 0 9px; font: inherit; font-size: 12px; color: var(--fg-2); border: 0; border-radius: 7px; background: var(--pill); white-space: nowrap; cursor: default; transition: background .12s, color .12s; }
.row.pref .proto.pick svg { opacity: .7; transition: transform .15s var(--ease); }
.row.pref .proto.pick.open svg { transform: rotate(180deg); }
.row.pref .proto.pick:hover, .row.pref .proto.pick.open { color: var(--fg); background: var(--pill-hover); }
.row.pref .proto.pick.busy { opacity: .6; }
.pop.proto-menu { width: 262px; max-height: none; padding: 4px; border: 1px solid var(--line); display: grid; gap: 1px; }
.proto-menu .pm-head { padding: 6px 8px 5px; font-size: 11px; color: var(--muted); }
.proto-menu .pm-item { display: flex; align-items: flex-start; gap: 7px; width: 100%; padding: 6px 8px 7px; border: 0; border-radius: 7px; background: none; color: var(--fg); font: inherit; text-align: left; cursor: default; outline: none; }
.proto-menu .pm-item:focus-visible, .proto-menu .pm-item:hover, .proto-menu .pm-item:focus { background: var(--pill); }
.proto-menu .pm-tick { width: 14px; height: 16px; flex: none; display: grid; place-items: center; color: var(--fg); }
.proto-menu .pm-words { display: grid; gap: 1px; min-width: 0; }
.proto-menu .pm-name { font-size: 12.5px; font-weight: 500; line-height: 16px; }
.proto-menu .pm-note { font-size: 11px; color: var(--muted); line-height: 15px; }
/* a subscription's allowance, under its name */
.accts .acc:has(.aq) { flex-wrap: wrap; row-gap: 3px; padding-top: 7px; padding-bottom: 8px; }
.acc .aq { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; padding-left: 25px; font-size: 10.5px; color: var(--muted); min-height: 14px; }
.acc .aq-w { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.acc .aq-track { width: 54px; height: 4px; border-radius: 2px; background: var(--pill); overflow: hidden; }
.acc .aq-track i { display: block; height: 100%; border-radius: inherit; background: var(--fg-2); }
.acc .aq-w b { color: var(--fg-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.acc .aq-w.full b, .acc .aq-w.full .aq-r { color: var(--fg); }
.acc .aq-w.full .aq-track i { background: var(--fg); }
.acc .aq-r { color: var(--muted); }
.acc .aq-none { color: var(--faint); }
.acc .skeleton.sk-aq { width: 110px; height: 8px; border-radius: 4px; }
.acc .dot.tick.fixed { cursor: default; }
.acc .dot.tick.fixed:hover { box-shadow: none; }
.acc.off .aq { opacity: .7; }
/* a sign-in under way, waiting on the browser */
.signing { display: flex; align-items: flex-start; gap: 11px; padding: 11px 10px 11px 12px; font-size: 12.5px; background: var(--card-2); animation: fade-in .2s; }
.sheet .signing { margin-top: 8px; border: 1px solid var(--line); border-radius: 10px; }
.signing .tt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; line-height: 1.35; }
.signing .n { font-weight: 500; }
.signing .s { color: var(--muted); font-size: 11.5px; overflow-wrap: anywhere; }
.signing > .text { margin: -3px 0; }
.signing .acts { display: flex; gap: 2px; margin: 2px 0 0 -4px; }
.signing .acts .link { color: var(--fg-2); }
.signing .devcode { display: flex; align-items: center; gap: 6px; margin: 6px 0 2px; }
.signing .devcode code { font: 600 17px/1.2 var(--mono, ui-monospace, monospace); letter-spacing: .12em; padding: 4px 9px; border: 1px solid var(--line); border-radius: 7px; background: var(--card); user-select: all; }
.signing .spinner { width: 16px; height: 16px; flex: none; margin-top: 1px; border-radius: 50%; border: 1.75px solid var(--line); border-top-color: var(--fg); animation: spin .8s linear infinite; }
.signing .mark { width: 16px; height: 16px; flex: none; margin-top: 1px; border-radius: 50%; display: grid; place-items: center; background: var(--fg); color: var(--card); font-size: 11px; font-weight: 700; }
.fallback { display: grid; gap: 6px; }
.fallback .fbl { display: grid; gap: 2px; }
.fbrow { display: flex; align-items: center; gap: 8px; min-height: 28px; font-size: 12.5px; }
.fbrow .i { width: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.fbrow .grow { flex: 1; }
.fallback .mchips:empty { display: none; }
.after-list { display: flex; align-items: center; gap: 8px; padding: 8px 4px 0; flex: none; }
.excluded { display: flex; align-items: flex-start; gap: 10px; padding: 10px 14px 2px; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
.excluded .ic { width: 16px; height: 16px; margin-top: 1px; opacity: .7; }
.excluded b { font-weight: 500; color: var(--fg-2); }
/* the add sheet: presets as tiles, one key away */
.sheet { padding: 6px 0 8px; flex: none; }
.sheet .row-head { padding: 0 2px; gap: 6px; }
.sheet .find, #view-gateway .find { height: 24px; width: 160px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); font-size: 12px; outline: none; transition: border-color .12s; }
.sheet .find:focus, #view-gateway .find:focus { border-color: var(--accent); }
.sheet .find::placeholder, #view-gateway .find::placeholder { color: var(--faint); }
.sheet .kind { font-size: 11.5px; color: var(--muted); padding: 10px 2px 5px; }
.sheet .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px; }
.sheet .none { padding: 14px 2px; color: var(--muted); font-size: 12px; }
#gwModels .none { padding: 16px; color: var(--muted); font-size: 12px; text-align: center; }
#view-gateway .row-head .find { margin-right: 8px; }
.tile {
position: relative; display: flex; align-items: center; gap: 10px;
height: 46px; padding: 0 10px 0 11px; border-radius: 10px; text-align: left; min-width: 0;
background: var(--card); border: 1px solid var(--line);
transition: border-color .12s, background .12s, box-shadow .12s;
}
.tile:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); background: var(--card-2); }
.tile.on { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.tile .ic { width: 20px; height: 20px; flex: none; }
.tile .ic.plus { color: var(--muted); border-radius: 6px; background: var(--pill); }
.tile .tt { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.tile .n { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile .n .badge { margin-left: 5px; }
.tile .s { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.tile.added { opacity: .5; }
.tile.added:hover { opacity: .8; }
.tile .check { margin-left: auto; color: var(--green); display: inline-flex; flex: none; }
.tile.custom { border-style: dashed; }
/* the provider editor, in a dialog */
.editor { padding: 16px 18px 14px; display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 10px 14px; align-items: start; }
.editor .ehead { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; padding-bottom: 8px; margin-bottom: 2px; border-bottom: 1px solid var(--line-2); }
.editor .ehead .ic { width: 20px; height: 20px; }
.editor .icon-pick { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.editor .icon-pick .icon-now { width: 32px; height: 32px; border: 1px solid var(--line); border-radius: 8px; display: grid; place-items: center; }
.editor .icon-pick .icon-now .ic { width: 20px; height: 20px; }
.editor .icon-pick .icon-grid { flex-basis: 100%; display: grid; grid-template-columns: repeat(auto-fill, 34px); gap: 4px; padding: 6px; border: 1px solid var(--line); border-radius: 10px; }
.editor .icon-pick .icon-grid button { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 7px; }
.editor .icon-pick .icon-grid button:hover { background: var(--card-2); }
.editor .icon-pick .icon-grid button.on { box-shadow: inset 0 0 0 1.5px var(--fg); }
.editor .icon-pick .icon-grid .ic { width: 18px; height: 18px; }
.editor .ehead b { font-weight: 600; }
.editor .ehead .note { font-size: 12px; color: var(--muted); }
.editor label { font-size: 12px; color: var(--muted); text-align: right; padding-top: 5px; }
.editor .hint { font-size: 11px; color: var(--faint); margin-top: 4px; }
.editor input[type="text"], .editor input[type="password"], .editor input[type="url"] {
height: 27px; padding: 0 9px; border-radius: 7px;
border: 1px solid var(--line); background: var(--card);
font-size: 12.5px; outline: none; width: 100%; min-width: 0;
transition: border-color .12s, box-shadow .12s;
}
.editor input:focus, .editor input:focus-visible, .editor .headers textarea.json:focus, .editor .headers textarea.json:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); outline: none; }
.editor input::placeholder { color: var(--faint); }
.editor .pair { display: flex; gap: 8px; align-items: center; }
.editor .pair input:first-child { flex: 1; }
.editor .side { display: flex; gap: 4px; align-items: center; flex: none; min-width: 52px; justify-content: flex-end; }
.editor .side .text { padding: 3px 6px; }
.editor .headers .pair .side .text { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border-radius: 6px; }
.editor .stack { display: flex; flex-direction: column; gap: 6px; }
.editor .headers { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.editor .headers .pair { width: 100%; }
.editor .headers .hadds { display: flex; flex-wrap: wrap; gap: 2px 12px; }
.editor .headers .pair input { flex: 1; min-width: 0; }
.editor .headers .pair input:first-child { flex: 4; }
.editor .headers .pair input:nth-child(2) { flex: 6; }
.editor .headers .pair .side { flex: none; }
.editor .headers .pair .side .text.on { color: var(--accent); }
.editor .headers .pair.col { flex-direction: column; align-items: stretch; }
.editor .headers .pair.col .hhead { display: flex; gap: 8px; align-items: center; width: 100%; }
.editor .headers .pair.col .hhead input { flex: 1; min-width: 0; }
.editor .headers .pair.col .side { flex: none; }
.editor .headers textarea.json { width: 100%; box-sizing: border-box; padding: 7px 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); color: var(--fg); outline: none; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.5; resize: vertical; tab-size: 2; white-space: pre; overflow: auto; transition: border-color .12s, box-shadow .12s; }
.editor .headers textarea.json.bad { border-color: var(--danger, #d66); }
.segs { position: relative; display: inline-flex; padding: 2px; border-radius: 7px; background: var(--pill); align-self: flex-start; }
.opt { position: relative; z-index: 1; white-space: nowrap; height: 22px; padding: 0 10px; border-radius: 5px; font-size: 12px; color: var(--muted); transition: color .18s var(--ease), transform .14s var(--ease); }
.opt.on { color: var(--fg); }
.opt:hover:not(.on) { color: var(--fg-2); }
.thumb {
position: absolute; top: 2px; bottom: 2px; left: 0; width: 0; border-radius: 6px;
background: var(--card); box-shadow: 0 1px 2px rgba(0, 0, 0, .12), 0 0 0 .5px rgba(0, 0, 0, .06);
transition: transform .28s var(--ease), width .28s var(--ease), opacity .15s;
pointer-events: none;
}
.segs .thumb { border-radius: 5px; }
.thumb.still { transition: none; }
.link { font-size: 12px; color: var(--accent); padding: 3px 4px; white-space: nowrap; }
.link:hover { text-decoration: underline; text-underline-offset: 2px; }
.editor .more { grid-column: 1 / -1; }
.editor .more summary { font-size: 12px; color: var(--muted); list-style: none; display: inline-flex; align-items: center; gap: 4px; padding: 2px 0; margin-left: 86px; }
.editor .more summary::-webkit-details-marker { display: none; }
.editor .more summary::before { content: "▸"; font-size: 10px; color: var(--faint); }
.editor .more[open] summary::before { content: "▾"; }
.editor .more summary:hover { color: var(--fg); }
.editor .more .inner { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 10px 14px; align-items: start; padding-top: 8px; }
.editor .warnbox { grid-column: 1 / -1; font-size: 12px; line-height: 1.5; color: var(--fg); background: color-mix(in srgb, var(--amber) 12%, transparent); border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent); border-radius: 8px; padding: 8px 10px; }
.editor .warnbox.soft { background: none; color: var(--amber); border: 0; padding: 0 0 0 86px; }
.editor.import .mchips .mchip { cursor: default; }
.editor .bar { grid-column: 1 / -1; display: flex; align-items: center; gap: 4px; padding-top: 10px; border-top: 1px solid var(--line-2); margin-top: 2px; }
.editor .bar .danger { margin-left: -7px; }
.editor .editor-error { grid-column: 1 / -1; font-size: 12px; line-height: 1.45; color: var(--red); white-space: pre-wrap; overflow-wrap: anywhere; user-select: text; -webkit-user-select: text; }
.editor .editor-error.warn { color: var(--amber); }
.busy { opacity: .55; pointer-events: none; }
/* agent chips: who is on this provider, click one to pick it a model */
.achips { display: flex; flex-wrap: wrap; gap: 5px; }
.achip {
display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 9px 0 6px; border-radius: 7px;
background: var(--card); border: 1px solid var(--line); font-size: 12px; color: var(--muted);
transition: background .12s, color .12s, border-color .12s;
}
.achip .ic { width: 15px; height: 15px; filter: grayscale(1); opacity: .55; transition: filter .12s, opacity .12s; }
.achip:hover { color: var(--fg); border-color: var(--muted); }
.achip:hover .ic, .achip.on .ic { filter: none; opacity: 1; }
.achip.on { color: var(--fg); background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.achip.open { border-color: var(--accent); }
.achip .m { font: 11px var(--code); color: var(--accent); }
/* endpoints, each with its own test result */
.eps { display: flex; flex-direction: column; gap: 3px; }
.ep { display: flex; align-items: center; gap: 8px; height: 24px; min-width: 0; }
.ep .pl { flex: none; width: 64px; font-size: 11.5px; color: var(--muted); }
.ep code { color: var(--fg-2); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; user-select: text; -webkit-user-select: text; cursor: text; }
.res { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 7px; border-radius: 5px; font-size: 11px; font-variant-numeric: tabular-nums; background: var(--pill); color: var(--muted); }
.res:empty { display: none; }
.res.wait { background: none; color: var(--faint); }
.res.ok { background: var(--green-soft); color: var(--green); }
.res.bad { background: var(--red-soft); color: var(--red); max-width: 60%; }
.res.bad span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eps .text { align-self: flex-start; margin: 5px 0 0 72px; }
/* model chips: click to expose, click again to hide */
.models { display: flex; flex-direction: column; gap: 6px; }
.models > input { max-width: 260px; }
.mchips { display: flex; flex-wrap: wrap; gap: 4px; max-height: 132px; overflow-y: auto; padding: 1px; }
.mchips::-webkit-scrollbar { width: 0; }
.mchip {
display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px; border-radius: 999px;
font-size: 11.5px; color: var(--muted); background: var(--card); border: 1px solid var(--line);
transition: background .12s, color .12s, border-color .12s;
}
.mchip:hover { color: var(--fg); border-color: var(--muted); }
.mchip.on { color: var(--accent); background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent); font-weight: 500; }
.mchip.on::before { content: "✓"; font-size: 10px; }
.mchip.own.on::before { content: "+"; }
/* how a model answered Test models: a dot after its name */
.mchip .tdot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--faint); }
.mchip .tdot.ok { background: var(--green); }
.mchip .tdot.bad { background: var(--red); }
.mchip .tdot.wait { animation: tdot 1s ease-in-out infinite alternate; }
@keyframes tdot { to { opacity: .25; } }
.mchips .hint, .mfoot .hint { font-size: 11px; color: var(--faint); align-self: center; line-height: 27px; }
.mfoot { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-height: 27px; }
.mfoot .hint { white-space: nowrap; }
.mfoot > input { height: 27px; }
.mfoot .text.action { flex: none; }
.mfoot input { max-width: 200px; height: 27px !important; }
.mfoot .text { padding: 2px 7px; }
.mfoot .text.on { color: var(--fg); background: var(--card-2); }
/* the models' own names and reasoning levels, one row each */
.mnames { display: grid; gap: 4px; max-height: 240px; overflow-y: auto; padding: 1px; }
.mnames[hidden] { display: none; }
.mnames > .hint { font-size: 11px; color: var(--faint); }
.mname { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--card); }
.mname .mwho { display: flex; align-items: center; gap: 8px; flex: 1 1 220px; min-width: 0; }
.mname .mwho input { flex: 1; min-width: 0; max-width: 220px; height: 25px; }
.mname .mwho code { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.mname .mlevels { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 11.5px; }
.editor .mname label.tick { gap: 4px; }
.mname .text { flex: none; padding: 2px 7px; font-size: 11.5px; }
/* ---------- settings ---------- */
#view-settings .row-head { margin: 4px 0 6px; padding: 0 2px; }
#view-settings .row-head + .list { margin-bottom: 8px; }
.row.pref { min-height: 50px; padding: 8px 12px 8px 14px; gap: 14px; }
.row.pref .who { flex: 1 1 auto; }
.row.pref .sub { margin-top: 2px; }
.row.pref .segs { flex: none; margin-left: auto; }
.proxy-segs { display: flex; align-items: center; gap: 8px; margin-left: auto; min-width: 0; }
.proxy-segs input.proxy, input.words { width: 180px; min-width: 0; height: 27px; padding: 0 9px; border-radius: 7px; border: 1px solid var(--line); background: var(--card); font-size: 12.5px; outline: none; transition: border-color .12s, box-shadow .12s; }
.proxy-segs input.proxy:focus, input.words:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.proxy-segs input.proxy::placeholder, input.words::placeholder { color: var(--faint); }
input.words { width: 240px; max-width: 100%; }
@media (max-width: 520px) { .proxy-segs { flex-wrap: wrap; justify-content: flex-end; } }
.prefs .val { display: inline-flex; align-items: center; gap: 2px; margin-left: auto; min-width: 0; max-width: 60%; flex: none; }
.prefs .val code { font-size: 12px; color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; user-select: text; -webkit-user-select: text; padding: 0 6px; }
.prefs .val .text { padding: 3px 6px; }
/* the community row's way in: Discord's own colour, quiet until hovered */
.prefs .val .discord {
display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 11px 0 9px; border-radius: 999px;
font-size: 12px; font-weight: 560; white-space: nowrap; color: #5865f2;
background: color-mix(in srgb, #5865f2 11%, transparent);
box-shadow: inset 0 0 0 .5px color-mix(in srgb, #5865f2 35%, transparent);
transition: background .15s, color .15s, transform .12s var(--ease);
}
.prefs .val .discord:hover { background: #5865f2; color: #fff; }
.prefs .val .discord:active { transform: scale(.96); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .prefs .val .discord:not(:hover) { color: #8b95ff; } }
:root[data-theme="dark"] .prefs .val .discord:not(:hover) { color: #8b95ff; }
/* ---------- motion ----------
One easing everywhere (iOS-ish: quick start, soft landing), short
durations, small distances. Pressing gives a little, pages settle in,
dialogs lift. */
:root { --ease: cubic-bezier(.2, .8, .2, 1); }
.text, .icon, .tile, .achip, .mchip, .use, .link {
transition-property: background, background-color, color, border-color, box-shadow, filter, opacity, transform;
transition-duration: .16s; transition-timing-function: var(--ease);
}
.text:active, .tile:active, .achip:active, .mchip:active, .use:active, .opt:active, .seg button:active { transform: scale(.96); }
.icon:active { transform: scale(.9); }
.row.provider { transition: background .16s var(--ease); }
.row.provider:active { background: var(--card-2); }
.chips .chip { transition: background .16s var(--ease), color .16s var(--ease), transform .14s var(--ease); }
.chips .chip:active { transform: scale(.96); }
.status { transition: opacity .2s var(--ease); }
/* the theme crossfades instead of snapping */
html.theming, html.theming *, html.theming *::before, html.theming *::after {
transition: background-color .35s var(--ease), background .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease), box-shadow .35s var(--ease) !important;
}
/* ---------- modal ---------- */
.modal {
position: fixed; inset: 0; z-index: 20;
display: flex; align-items: center; justify-content: center; padding: 28px 24px;
background: rgba(0, 0, 0, .28);
-webkit-backdrop-filter: blur(8px) saturate(1.1); backdrop-filter: blur(8px) saturate(1.1);
animation: fade-in .2s var(--ease);
}
.modal.out { animation: fade-out .16s var(--ease) forwards; pointer-events: none; }
.modal .dialog {
width: min(600px, 100%); min-width: 0; max-height: 100%; overflow-y: auto;
border-radius: 14px; background: var(--card);
box-shadow: 0 0 0 1px var(--line), 0 24px 60px rgba(0, 0, 0, .32), 0 2px 8px rgba(0, 0, 0, .12);
animation: dialog-in .26s var(--ease);
}
.modal .dialog.swap { animation: content-in .22s var(--ease); }
.modal.out .dialog { animation: dialog-out .16s var(--ease) forwards; }
.modal .dialog::-webkit-scrollbar { width: 0; }
/* Keep native window chrome outside the scrim and dialog. In particular, the
macOS traffic lights must never sit on top of modal content. */
body.window.mac .modal { top: 50px; padding: 16px 24px 24px; }
body.window .modal { padding: 16px 24px 24px; }
body.panel .modal { padding: 16px 12px; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
@keyframes dialog-in { from { opacity: 0; transform: translateY(12px) scale(.97); } }
@keyframes dialog-out { to { opacity: 0; transform: translateY(6px) scale(.98); } }
@keyframes content-in { from { opacity: .5; transform: translateY(2px); } }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
.skeleton { animation: none !important; }
}
/* Import from other apps: a checklist per app */
.editor.importapps { grid-template-columns: minmax(0, 1fr); }
.editor.importapps .appnote { font-size: 12px; color: var(--muted); line-height: 1.5; }
.editor.importapps .applist { display: flex; flex-direction: column; gap: 14px; max-height: min(56vh, 460px); overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.editor.importapps .apptabs { display: flex; gap: 4px; padding: 3px; border-radius: 10px; background: var(--pill); overflow-x: auto; scrollbar-width: none; }
.editor.importapps .apptab { flex: 1 1 0; min-width: max-content; display: flex; align-items: center; justify-content: center; gap: 7px; padding: 6px 12px; border-radius: 7px; font-size: 12.5px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.editor.importapps .apptab:hover { color: var(--fg); }
.editor.importapps .apptab.on { background: var(--card); color: var(--fg); box-shadow: 0 1px 2px rgba(0,0,0,.18); }
.editor.importapps .apptab.missing .applogo { filter: grayscale(1); opacity: .5; }
.editor.importapps .apptab .count { min-width: 16px; padding: 0 5px; border-radius: 8px; font-size: 10.5px; line-height: 16px; text-align: center; color: var(--fg-2); background: var(--line); }
.editor.importapps .apptab.missing .count { background: none; color: var(--faint); }
.editor.importapps .apphead > .applogo, .editor.importapps .apphead > b { display: none; }
.editor.importapps .apphead { display: flex; align-items: baseline; gap: 8px; padding-bottom: 4px; }
.editor.importapps .apphead b { font-weight: 600; font-size: 13px; flex: none; }
.editor.importapps .apphead { align-items: center; }
.editor.importapps .applogo { width: 18px; height: 18px; flex: none; border-radius: 4px; }
.editor.importapps .appall { flex: none; display: flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 400; color: var(--muted); text-align: left; cursor: pointer; padding-right: 6px; }
.editor.importapps .appall input { margin: 0; accent-color: var(--fg); }
.editor.importapps .apphead code { flex: 1; min-width: 0; font: 11px var(--code); color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor.importapps .appempty { font-size: 12px; color: var(--muted); padding: 2px 0 4px; }
.editor.importapps .approw { text-align: left; font-weight: 400; color: var(--fg); display: flex; align-items: flex-start; gap: 10px; padding: 8px 6px; border-radius: 8px; cursor: pointer; }
.editor.importapps .approw:hover:not(.dim) { background: var(--pill); }
.editor.importapps .approw.dim { cursor: default; opacity: .55; }
.editor.importapps .approw input { margin: 3px 0 0; accent-color: var(--fg); flex: none; }
.editor.importapps .approw .ic { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.editor.importapps .approw .appwho { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.editor.importapps .approw .name { display: flex; align-items: baseline; gap: 6px; font-size: 13px; }
.editor.importapps .approw .name .from { font-size: 11px; color: var(--muted); }
.editor.importapps .approw .sub { font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
.editor.importapps .approw .segs { margin-top: 3px; max-width: 100%; overflow-x: auto; }
.editor.importapps .approw .segs .opt { white-space: nowrap; flex: none; }
.editor.importapps .apptag { flex: none; font-size: 11px; color: var(--fg-2); background: var(--pill); border-radius: 5px; padding: 1px 6px; margin-top: 1px; }
.editor.importapps .bar .note { font-size: 12px; color: var(--muted); }
/* sync and backup, on the Settings page */
.prefs .sub.bad { color: var(--red); }
.prefs .sync-note .who .sub + .sub { margin-top: 2px; }
.editor.sync-form { grid-template-columns: 86px minmax(0, 1fr); }
.editor label.tick { display: flex; align-items: center; gap: 7px; text-align: left; padding-top: 0; color: var(--fg-2); cursor: pointer; }
.editor label.tick input { margin: 0; }
.editor .fname { flex: 1; min-width: 0; font-size: 12.5px; color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor.sync-form .done { grid-column: 1 / -1; font-size: 12.5px; color: var(--fg-2); user-select: text; -webkit-user-select: text; }
.editor.sync-form .bar { grid-column: 1 / -1; }