/* LLeMbas Desktop's page. Every colour, size, space and font is a token from tokens.css (the server's, copied by scripts/fetch-tokens.sh and pinned); the only values of this page's own are the title bar's height, the setup card's width and the activity panel's number columns, named below. Media queries cannot read a custom property, so the two breakpoints are written out and named after the tokens they are: 48rem is --bp-narrow (the sidebar becomes a drawer), 64rem is --bp-wide (the viewer goes over the chat instead of beside it). Rows line up by construction: every row of controls sits on a grid with known tracks, a field is always three parts (label, control, hint) on shared rows, and nothing is aligned by `baseline` across text of unknown length. */ * { box-sizing: border-box; } :root { /* The title bar's height: a fact of this page, not a token the server has. */ --titlebar-h: 36px; /* The setup card's widest. */ --card-max: 40rem; /* The sidebar toggle's track in the title bar: none until the sidebar is a drawer. */ --side-btn-w: 0px; /* The activity panel's number columns: a token count or a share ("180k", "63.0%"), and an elapsed time ("2h 03m"), in the panel's monospaced figures. */ --num-col: 4.5em; --time-col: 5.5em; } html, body { margin: 0; height: 100%; overflow: hidden; } body { background: var(--bg); color: var(--ink); font: var(--text-base) / var(--leading-normal) var(--font-body); } [hidden] { display: none !important; } .app { display: grid; grid-template-rows: var(--titlebar-h) minmax(0, 1fr); height: 100vh; } h1, h2, h3, p { margin: 0; } .muted { color: var(--ink-muted); font-size: var(--text-sm); } .is-error { color: var(--warning); } bdi { unicode-bidi: isolate; } .icon { width: 16px; height: 16px; fill: currentColor; flex: none; } /* --- Controls ------------------------------------------------------------------------------ */ .btn { height: var(--control-h); padding: 0 var(--sp-4); display: inline-grid; grid-auto-flow: column; gap: var(--sp-2); align-items: center; justify-content: center; font: 600 var(--text-sm) var(--font-ui); color: var(--ink); background: var(--surface); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-block); cursor: pointer; white-space: nowrap; } .btn:hover { background: var(--surface-hover); } .btn:active { transform: translate(var(--press), var(--press)); box-shadow: none; } .btn:disabled { opacity: var(--opacity-dim); cursor: default; } .btn--primary { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); } .btn--primary:hover { background: var(--accent-hover); } .btn--sm { height: var(--control-h-sm); padding: 0 var(--sp-3); box-shadow: none; } .btn--danger { color: var(--ink-inverse); background: var(--danger); border-color: var(--danger); } .btn--danger:hover { background: var(--danger-hover); } input[type="text"], input[type="number"], select, textarea { min-width: 0; font: var(--text-sm) var(--font-ui); color: var(--ink); background: var(--bg); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); } input[type="text"], input[type="number"], select { height: var(--control-h); padding: 0 var(--control-px-sm); } textarea { padding: var(--sp-2) var(--control-px-sm); resize: none; line-height: var(--leading-normal); } :focus-visible { outline: var(--outline-w) solid var(--accent); outline-offset: var(--outline-offset); } label, .label { font: var(--text-sm) / var(--leading-tight) var(--font-ui); color: var(--ink-muted); } .hint { font-size: var(--text-sm); color: var(--ink-muted); min-height: calc(var(--text-sm) * var(--leading-normal)); } .status { font: var(--text-sm) / var(--leading-normal) var(--font-ui); } .status.is-ok { color: var(--leaf); } .check { display: grid; grid-template-columns: var(--check-size) minmax(0, 1fr); gap: var(--sp-2); align-items: center; color: var(--ink); } .check input { width: var(--check-size); height: var(--check-size); margin: 0; accent-color: var(--accent); } .chip { display: inline-block; padding: 0 var(--sp-2); font: var(--text-xs) / 1.6 var(--font-ui); color: var(--ink-muted); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); white-space: nowrap; } .chip--leaf { color: var(--leaf); border-color: var(--leaf); } .dot { width: var(--dot-size); height: var(--dot-size); background: var(--ink-faint); flex: none; } .dot.is-ok { background: var(--leaf); } .dot.is-busy { background: var(--accent); } .dot.is-new { background: var(--leaf); } .dot.is-error { background: var(--warning); } /* A field is three stacked parts on fixed rows: label, control, hint -- always all three. */ .field { display: grid; grid-template-rows: auto var(--control-h) auto; gap: var(--sp-2); align-content: start; } .fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); grid-auto-rows: auto var(--control-h) auto; column-gap: var(--sp-4); row-gap: var(--sp-2); } /* Each field spans three shared rows, so side-by-side controls sit on one line whatever their labels and hints do. */ .fields .field { grid-row: span 3; grid-template-rows: subgrid; } .row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-2); } .row--buttons { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); gap: var(--sp-2); } /* A section's heading in brackets, as on the server's screens: `[ SERVER ]`. */ .card h2, .set h2 { margin: 0 0 var(--sp-3); font: 600 var(--text-sm) / var(--leading-tight) var(--font-ui); letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); } .card h2::before, .set h2::before { content: "[ "; } .card h2::after, .set h2::after { content: " ]"; } .code { font: 700 var(--text-xl) / var(--leading-tight) var(--font-mono); letter-spacing: 0.15em; color: var(--leaf); margin: var(--sp-2) 0 var(--sp-3); } /* --- The title bar ------------------------------------------------------------------------- */ .bar { display: grid; /* side · leaf · name · host (the rest, and the drag area) · update · agent · menu · sep · 3 controls */ grid-template-columns: var(--side-btn-w) var(--titlebar-h) auto minmax(0, 1fr) auto auto var(--titlebar-h) var(--border-w) repeat(3, 2.875rem); align-items: center; height: var(--titlebar-h); border-bottom: var(--border-w) solid var(--border); background: var(--bg); font: 600 var(--text-sm) / 1 var(--font-ui); user-select: none; -webkit-user-select: none; cursor: default; } .bar button { height: var(--titlebar-h); margin: 0; padding: 0; font: inherit; color: var(--ink-muted); background: transparent; border: 0; border-radius: 0; cursor: pointer; } .bar button:hover { color: var(--ink); background: var(--surface-hover); } .bar button:focus-visible { outline-offset: calc(-1 * var(--outline-w)); } .bar__leaf { justify-self: center; width: 18px; height: 18px; } .bar__name b { color: var(--leaf); font-weight: 700; } .bar__host { padding: 0 var(--sp-3); color: var(--ink-muted); font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; align-self: stretch; display: flex; align-items: center; } .bar__btn { display: grid; place-items: center; } .bar__side { overflow: hidden; visibility: hidden; } .bar__agent { display: grid; grid-template-columns: var(--dot-size) auto; gap: var(--sp-2); align-items: center; padding: 0 var(--sp-3) !important; font-weight: 400 !important; } .bar__agent[data-state="running"] .dot, .bar__agent[data-state="elsewhere"] .dot { background: var(--leaf); } .bar__agent[data-state="starting"] .dot, .bar__agent[data-state="connecting"] .dot { background: var(--accent); } .bar__agent[data-state="failed"] .dot, .bar__agent[data-state="not_linked"] .dot, .bar__agent[data-state="no_folders"] .dot, .bar__agent[data-state="waiting"] .dot, .bar__agent[data-state="refused"] .dot, .bar__agent[data-state="elsewhere_waiting"] .dot { background: var(--warning); } .bar__update { padding: 0 var(--sp-3) !important; color: var(--accent-ink) !important; background: var(--accent) !important; } .bar__update:hover { background: var(--accent-hover) !important; } /* Hidden keeps its grid track (auto, so zero wide): the slots after it never move. */ .bar__update[hidden] { display: block !important; width: 0; padding: 0 !important; overflow: hidden; visibility: hidden; } .bar__sep { width: var(--border-w); height: var(--sp-5); background: var(--border); } .bar__btn--close:hover { color: var(--ink-inverse) !important; background: var(--danger) !important; } /* --- Setup --------------------------------------------------------------------------------- */ .setup { overflow: auto; display: grid; place-items: center; padding: var(--sp-4); } .card { width: min(100%, var(--card-max)); display: grid; gap: var(--sp-6); padding: var(--sp-8); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-block-lg); } .setup__body { display: grid; gap: var(--sp-6); } .setup__body section { display: grid; gap: var(--sp-3); } .brand { display: grid; grid-template-columns: var(--sp-10) minmax(0, 1fr); gap: var(--sp-3); align-items: center; } .brand img { width: var(--sp-10); height: var(--sp-10); } .brand h1 { font: 600 var(--text-xl) / var(--leading-tight) var(--font-ui); } .brand h1 b { color: var(--leaf); font-weight: 700; } /* --- The shell ----------------------------------------------------------------------------- */ .shell { position: relative; min-height: 0; display: grid; grid-template-columns: var(--sidebar-width) minmax(0, 1fr); grid-template-areas: "side main"; } .shell[data-viewer="true"] { grid-template-columns: var(--sidebar-width) minmax(0, 1fr) minmax(var(--inspector-width-min), 42%); grid-template-areas: "side main viewer"; } /* The sidebar: the switch, the new-chat button, the chats, then the two explorers (each a row of its own that takes room only while open), then settings. */ .side { grid-area: side; min-height: 0; display: grid; --local-row: auto; --server-row: auto; grid-template-rows: auto auto minmax(calc(3 * var(--row-h)), 2fr) var(--local-row) var(--server-row) auto; border-right: var(--border-w) solid var(--border); background: var(--bg-sunken); } .side[data-local="true"] { --local-row: minmax(calc(4 * var(--row-h)), 1.5fr); } .side[data-server="true"] { --server-row: minmax(calc(4 * var(--row-h)), 1.5fr); } .switch { display: grid; grid-template-columns: 1fr 1fr; border-bottom: var(--border-w) solid var(--border); } .switch button { height: var(--control-h); font: 600 var(--text-sm) var(--font-ui); color: var(--ink-muted); background: transparent; border: 0; border-bottom: var(--border-w-accent) solid transparent; border-radius: var(--radius-none); cursor: pointer; } .switch button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); background: var(--surface); } .side__new { margin: var(--sp-3); } .list { list-style: none; margin: 0; padding: 0 0 var(--sp-2); overflow: auto; min-height: 0; } .list__head { padding: var(--sp-2) var(--sp-3) var(--sp-1); font: 600 var(--text-xs) var(--font-ui); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-faint); } .list__note { padding: var(--sp-3); font-size: var(--text-sm); color: var(--ink-muted); } .list__more { margin: var(--sp-2) var(--sp-3); } /* A chat's row: dot · title · when, and under them its folder -- fixed tracks, so rows with long titles or no folder keep their dots and times on the same lines. */ .chatrow { width: 100%; display: grid; grid-template-columns: var(--dot-size) minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: var(--sp-2); align-items: center; min-height: var(--row-h); padding: var(--sp-2) var(--sp-3); text-align: left; font: var(--text-sm) / var(--leading-tight) var(--font-ui); color: var(--ink); background: transparent; border: 0; border-left: var(--border-w-accent) solid transparent; cursor: pointer; } .chatrow:hover { background: var(--surface-hover); } .chatrow[aria-current="true"] { background: var(--surface-active); border-left-color: var(--accent); } .chatrow.is-unread .row__title { font-weight: 700; } .row__title, .row__sub { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .row__when { font-size: var(--text-xs); color: var(--ink-faint); } .row__sub { grid-column: 2 / 4; font-size: var(--text-xs); color: var(--ink-muted); direction: rtl; text-align: left; } /* The explorers. */ .pane { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); border-top: var(--border-w) solid var(--border); } .pane[data-open="false"] .pane__body { display: none; } .pane__head { display: grid; grid-template-columns: minmax(0, 1fr) var(--control-h-sm); align-items: center; } .pane__toggle { height: var(--control-h); display: grid; grid-template-columns: 1rem minmax(0, 1fr); gap: var(--sp-1); align-items: center; padding: 0 var(--sp-3); text-align: left; font: 600 var(--text-xs) var(--font-ui); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); background: transparent; border: 0; cursor: pointer; } .pane__toggle[aria-expanded="true"] .tree__chevron .icon { transform: rotate(90deg); } .pane__btn { width: var(--control-h-sm); height: var(--control-h-sm); display: grid; place-items: center; padding: 0; color: var(--ink-muted); background: transparent; border: 0; border-radius: var(--radius); cursor: pointer; } .pane__btn:hover { color: var(--ink); background: var(--surface-hover); } .pane__body { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); } .pane__where { padding: 0 var(--sp-3) var(--sp-2); } .pane__where:empty { display: none; } .pane__pick { width: 100%; height: var(--control-h-sm); } .pane__path { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; direction: rtl; text-align: left; font: var(--text-xs) var(--font-ui); color: var(--ink-muted); } .pane__tree { overflow: auto; min-height: 0; padding-bottom: var(--sp-2); } .pane__note { padding: var(--sp-2) var(--sp-3); font-size: var(--text-sm); color: var(--ink-muted); } .pane__tree > .btn { margin: 0 var(--sp-3); } .tree, .tree ul { list-style: none; margin: 0; padding: 0; } .tree__row { width: 100%; height: var(--row-h); display: grid; grid-template-columns: calc(var(--depth, 0) * var(--sp-3)) 1rem 1rem minmax(0, 1fr) auto; gap: var(--sp-1); align-items: center; padding: 0 var(--sp-3); text-align: left; font: var(--text-xs) var(--font-ui); color: var(--ink); background: transparent; border: 0; cursor: pointer; } /* The indent's track needs an item of its own, or the chevron would sit in it. */ .tree__row::before { content: ""; } .tree__row:hover { background: var(--surface-hover); } .tree__row .icon { color: var(--ink-muted); } .tree__chevron { display: grid; place-items: center; width: 1rem; } .tree__chevron .icon { width: 12px; height: 12px; transition: transform var(--dur-1) var(--ease-out); } .tree__row[aria-expanded="true"] .tree__chevron .icon { transform: rotate(90deg); } .tree__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .tree__size { color: var(--ink-faint); } .tree__note { padding: var(--sp-1) var(--sp-3); font-size: var(--text-xs); color: var(--ink-muted); } .side__settings { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: var(--sp-2); align-items: center; height: var(--control-h); padding: 0 var(--sp-3); text-align: left; font: var(--text-sm) var(--font-ui); color: var(--ink-muted); background: transparent; border: 0; border-top: var(--border-w) solid var(--border); cursor: pointer; } .side__settings:hover { color: var(--ink); background: var(--surface-hover); } .scrim { display: none; } /* --- The chat ------------------------------------------------------------------------------ */ .main, .settings { grid-area: main; min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto auto; } .settings { grid-template-rows: auto minmax(0, 1fr); } .head { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; min-height: var(--header-height); padding: 0 var(--sp-4); border-bottom: var(--border-w) solid var(--border); } .head__title { font: 600 var(--text-md) / var(--leading-tight) var(--font-ui); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .head__place { display: flex; gap: var(--sp-2); align-items: center; min-width: 0; } .head__dir { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; direction: rtl; text-align: left; font: var(--text-xs) var(--font-ui); color: var(--ink-muted); min-width: 0; } .head__tools { display: flex; gap: var(--sp-2); align-items: center; } .head__mode { height: var(--control-h-sm); } .thread { overflow: auto; min-height: 0; padding: var(--sp-4); scroll-behavior: auto; } .thread > * { max-width: var(--thread-max-width); margin-left: auto; margin-right: auto; } .thread__note { padding: var(--sp-2) 0; font-size: var(--text-sm); } .thread__loading { padding: var(--sp-4) 0; } .thread__earlier { display: block; margin: 0 auto var(--sp-4); } .messages { display: grid; gap: var(--sp-5); } .new { display: grid; gap: var(--sp-4); padding: var(--sp-4) 0; } .new__warn { color: var(--warning); font-size: var(--text-sm); } .new select { width: 100%; } .msg { display: grid; gap: var(--sp-3); min-width: 0; } .msg--user { justify-self: end; max-width: min(100%, var(--w-prose)); padding: var(--sp-3) var(--sp-4); background: var(--bubble-user); border: var(--border-w) solid var(--border); border-radius: var(--radius-lg); } .msg--user.is-queued { opacity: var(--opacity-dim); } .msg--user.is-machine { justify-self: stretch; max-width: none; font-size: var(--text-sm); color: var(--ink-muted); background: transparent; } .msg__text { white-space: pre-wrap; overflow-wrap: anywhere; } .msg__files { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--sp-1); font-size: var(--text-xs); } .msg__note { font-size: var(--text-sm); color: var(--ink-muted); } .msg__foot { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; } .msg__files .chip { max-width: var(--w-chip); overflow: hidden; text-overflow: ellipsis; } /* Under a message: small icon buttons, all one size. */ .msg__actions { display: grid; grid-auto-flow: column; grid-auto-columns: var(--control-h-sm); justify-content: start; } .msg--user .msg__actions { justify-content: end; margin-top: calc(-1 * var(--sp-2)); } .msg__act { display: grid; place-items: center; width: var(--control-h-sm); height: var(--control-h-sm); padding: 0; color: var(--ink-faint); background: none; border: 0; border-radius: var(--radius); cursor: pointer; } .msg__act:hover, .msg__act:focus-visible { color: var(--ink); background: var(--surface-hover); } /* Regenerate: on the last reply only, and not while it is being written. */ .msg__regen { display: none; } .messages > .msg--assistant:last-child:not(.is-live) .msg__regen { display: grid; } .msg__editor { display: grid; gap: var(--sp-2); } .msg__edit { width: 100%; min-height: var(--control-h); font: var(--text-base) / var(--leading-normal) var(--font-body); resize: vertical; } .msg__editbar { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(min(100%, 6rem), auto); gap: var(--sp-2); justify-content: end; } .chip--model { display: inline-grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-1); align-items: center; max-width: var(--w-chip); padding-left: var(--sp-1); } .chip--model > span:last-child { overflow: hidden; text-overflow: ellipsis; } /* A model's avatar: its initial on its own colour. Only the hue is the model's (models.js, the server's stable_hue); how strong it is comes from the theme, by mixing it into the surface. */ .avatar { display: inline-grid; place-items: center; width: 1.25rem; height: 1.25rem; font: 700 var(--text-xs) / 1 var(--font-ui); color: var(--ink); background: color-mix(in oklab, hsl(var(--avatar-hue, 40) 100% 50%) 32%, var(--surface)); border-radius: var(--radius-sm); flex: none; } .avatar--none { background: var(--surface-active); } /* A model's own picture fills the same square, cut to it: the avatar's size does not depend on it. */ .avatar--image { overflow: hidden; background: var(--surface); } .avatar--image img { display: block; width: 100%; height: 100%; object-fit: cover; } /* The Thinking switch: a checkbox drawn as a switch, then its words, on two known tracks. The label is the tap target; the whole of it is a control's height. */ .toggle { display: inline-grid; grid-template-columns: calc(2 * var(--check-size)) auto; gap: var(--sp-2); align-items: center; height: var(--control-h); color: var(--ink); font: var(--text-sm) var(--font-ui); cursor: pointer; white-space: nowrap; } .toggle--compact { height: var(--control-h-sm); } .toggle input { appearance: none; position: relative; width: calc(2 * var(--check-size)); height: var(--check-size); margin: 0; background: var(--surface-active); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius-full); cursor: pointer; transition: background var(--dur-1) var(--ease-out); } .toggle input::after { content: ""; position: absolute; top: var(--border-w); left: var(--border-w); width: calc(var(--check-size) - 4 * var(--border-w)); height: calc(var(--check-size) - 4 * var(--border-w)); background: var(--ink-muted); border-radius: var(--radius-full); transition: transform var(--dur-1) var(--ease-out); } .toggle input:checked { background: var(--accent); border-color: var(--accent); } .toggle input:checked::after { background: var(--accent-ink); transform: translateX(var(--check-size)); } /* The team's size: two number fields of one width with a dash between them, and in the header its word before them -- fixed tracks, so nothing moves when a number grows a digit. */ .agents { display: inline-grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; width: 100%; height: var(--control-h); } .agents__dash { color: var(--ink-muted); } .agents__input { width: 100%; min-width: 0; height: var(--control-h); padding: 0 var(--control-px-sm); } .agents--compact { grid-template-columns: auto calc(var(--w-field-xs) / 2) auto calc(var(--w-field-xs) / 2); width: auto; height: var(--control-h-sm); font: var(--text-sm) var(--font-ui); } .agents--compact .agents__input { height: var(--control-h-sm); } .agents__label { color: var(--ink-muted); white-space: nowrap; } /* The model picker: a button the height of a control, avatar · name · chevron. */ .picker { display: inline-grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; height: var(--control-h); max-width: 100%; padding: 0 var(--control-px-sm); font: var(--text-sm) var(--font-ui); color: var(--ink); text-align: left; background: var(--bg); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); cursor: pointer; } .picker__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .head__model { display: flex; gap: var(--sp-2); align-items: center; min-width: 0; } .head__model .picker { height: var(--control-h-sm); max-width: var(--w-chip); } .new .picker { width: 100%; } .msg__metrics { font: var(--text-xs) var(--font-ui); color: var(--ink-faint); } .msg__steps { display: grid; gap: var(--sp-3); min-width: 0; } .msg__status, .msg__thinking { font: var(--text-xs) var(--font-ui); } .msg__status.is-error { color: var(--warning); } .msg__jobs { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-1); font-size: var(--text-sm); } .job { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; } .step--thinking summary, .call__head { cursor: pointer; font: var(--text-sm) var(--font-ui); color: var(--ink-muted); } .step__pre { margin-top: var(--sp-2); padding-left: var(--sp-3); border-left: var(--border-w-thick) solid var(--border); white-space: pre-wrap; font-size: var(--text-sm); color: var(--ink-muted); } .step--tools { display: grid; gap: var(--sp-1); } .step--steer { padding-left: var(--sp-3); border-left: var(--border-w-thick) solid var(--accent-soft); } .steer__text { white-space: pre-wrap; font-size: var(--text-sm); } .call { border: var(--border-w) solid var(--border); border-radius: var(--radius); background: var(--surface); min-width: 0; } .call.is-failed { border-color: var(--warning); } /* The call's line: dot · title · chips, on fixed tracks. */ .call__head { list-style: none; display: grid; grid-template-columns: var(--dot-size) minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; min-height: var(--row-h); padding: 0 var(--sp-3); } .call__head::-webkit-details-marker { display: none; } .call__title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--ink); font-family: var(--font-mono); } .call__chips { display: flex; gap: var(--sp-1); } .call__body { display: grid; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3) var(--sp-3); border-top: var(--border-w) solid var(--border); } .call__pre, .md-code pre { margin: 0; padding: var(--sp-2) var(--sp-3); max-height: var(--h-list); overflow: auto; font: var(--text-xs) / var(--leading-normal) var(--font-mono); background: var(--code-bg); border: var(--border-w) solid var(--code-border); border-radius: var(--radius); white-space: pre; } .call__open { justify-self: start; margin: 0 var(--sp-3) var(--sp-3); } /* Markdown, drawn by markdown.js from model output (never as HTML). */ .md { overflow-wrap: anywhere; min-width: 0; } .md > * + * { margin-top: var(--sp-3); } .md h1, .md h2, .md h3, .md h4, .md h5, .md h6 { font-family: var(--font-ui); line-height: var(--leading-tight); } .md h1 { font-size: var(--text-xl); } .md h2 { font-size: var(--text-lg); } .md h3 { font-size: var(--text-md); } .md h4, .md h5, .md h6 { font-size: var(--text-base); } .md ul, .md ol { margin: 0; padding-left: var(--sp-6); } .md li + li { margin-top: var(--sp-1); } .md-task { list-style: none; margin-left: calc(-1 * var(--sp-5)); } .md-task input { margin: 0 var(--sp-2) 0 0; } .md blockquote { margin: 0; padding-left: var(--sp-3); border-left: var(--border-w-thick) solid var(--border-strong); color: var(--ink-muted); } .md hr { border: 0; border-top: var(--border-w) solid var(--border); } .md code { font: 0.9em var(--font-mono); padding: 0 var(--sp-1); background: var(--code-bg); border-radius: var(--radius-sm); } .md pre code { padding: 0; background: none; } .md a { color: var(--accent); } .md a.md-unsafe { color: var(--ink-muted); text-decoration: line-through dotted; } .md-code { position: relative; display: grid; } .md-lang { position: absolute; top: var(--sp-1); left: var(--sp-3); font: var(--text-xs) var(--font-ui); color: var(--ink-faint); } .md-code:has(.md-lang) pre { padding-top: var(--sp-6); } .md-copy { position: absolute; top: var(--sp-1); right: var(--sp-1); height: var(--control-h-sm); padding: 0 var(--sp-2); font: var(--text-xs) var(--font-ui); color: var(--ink-muted); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); cursor: pointer; } /* A wide table scrolls by itself; the page does not. */ .md-table { overflow-x: auto; } .md table { border-collapse: collapse; font-size: var(--text-sm); } .md th, .md td { padding: var(--sp-1) var(--sp-3); border: var(--border-w) solid var(--border); text-align: left; vertical-align: top; } .md [data-align="center"] { text-align: center; } .md [data-align="right"] { text-align: right; } .md th { background: var(--surface); } /* Cards: what waits for an answer, above the composer. */ .cards { overflow: auto; max-height: 50vh; padding: var(--sp-3) var(--sp-4) 0; display: grid; gap: var(--sp-3); } .ask { width: 100%; max-width: var(--thread-max-width); margin: 0 auto; display: grid; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--surface-raised); border: var(--border-w-accent) solid var(--accent); border-radius: var(--radius); box-shadow: var(--shadow-block-accent); } .ask__item { display: grid; gap: var(--sp-2); } .ask__header { font: 600 var(--text-xs) var(--font-ui); text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent); } .ask__title { font-weight: 600; } .ask__edit { width: 100%; font-family: var(--font-mono); } .ask__text { width: 100%; } .ask__options { display: grid; gap: var(--sp-2); } .opt { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: var(--sp-2); align-items: center; min-height: var(--control-h); padding: var(--sp-2) var(--sp-3); text-align: left; font: var(--text-sm) var(--font-body); color: var(--ink); background: var(--bg); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); cursor: pointer; } .opt[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); } .opt__desc { grid-column: 1; font-size: var(--text-xs); color: var(--ink-muted); } .opt .chip { grid-column: 2; grid-row: 1; } .ask__actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr)); gap: var(--sp-2); } .ask__said { font-size: var(--text-sm); color: var(--warning); } .ask__said:empty { display: none; } .plan { margin: 0; padding-left: var(--sp-5); display: grid; gap: var(--sp-2); font-size: var(--text-sm); } .plan ul { margin: var(--sp-1) 0 0; padding-left: var(--sp-4); } .plan__phase { font-weight: 600; } .plan__task.is-done { text-decoration: line-through; color: var(--ink-muted); } /* The composer: the files it carries on a row of their own, then three tracks -- the attach button, the text, the send buttons. The buttons are one control high and sit at the foot of the row the text sets the height of: their size is known, the text's is not. */ .composer { position: relative; display: grid; grid-template-columns: var(--control-h) minmax(0, 1fr) auto; grid-template-areas: "files files files" "attach text actions"; /* No gap between the rows: the files' row has its own margin, and none while it is empty. */ gap: 0 var(--sp-2); padding: var(--sp-3) var(--sp-4) var(--sp-4); } .composer[data-attach="false"] { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "files files" "text actions"; } .composer > * { min-width: 0; } .composer textarea { grid-area: text; width: 100%; min-height: var(--control-h); max-height: 40vh; font: var(--text-base) / var(--leading-normal) var(--font-body); } .composer__attach { grid-area: attach; align-self: end; width: var(--control-h); padding: 0; } .composer__actions { grid-area: actions; align-self: end; display: grid; grid-auto-flow: column; gap: var(--sp-2); } .composer__files { grid-area: files; margin: 0 0 var(--sp-2); padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--w-chip)), 1fr)); gap: var(--sp-2); } /* One file: name · size or state · remove, the same tracks on every row. */ .file { display: grid; grid-template-columns: minmax(0, 1fr) auto var(--control-h-sm); gap: var(--sp-2); align-items: center; height: var(--control-h-sm); padding-left: var(--sp-2); font: var(--text-xs) var(--font-ui); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); } .file__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--ink); } .file__state { color: var(--ink-muted); max-width: var(--w-chip); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .file.is-failed { border-color: var(--warning); } .file.is-failed .file__state { color: var(--warning); } .file__remove { display: grid; place-items: center; height: 100%; padding: 0; color: var(--ink-muted); background: none; border: 0; border-left: var(--border-w) solid var(--border); cursor: pointer; } .file__remove:hover { color: var(--ink); background: var(--surface-hover); } /* Files dragged over the window: where they will go, over the whole composer. */ .composer__drop { display: none; } .composer[data-drag="true"] .composer__drop { display: grid; place-items: center; position: absolute; inset: var(--sp-2) var(--sp-4); z-index: var(--z-raised); font: 600 var(--text-sm) var(--font-ui); color: var(--accent); background: var(--accent-soft); border: var(--border-w-thick) dashed var(--accent); border-radius: var(--radius); } /* --- Settings ------------------------------------------------------------------------------ */ .settings__body { overflow: auto; padding: var(--sp-4); display: grid; gap: var(--sp-6); align-content: start; } .settings__body > .set { width: 100%; max-width: var(--w-prose); margin: 0 auto; display: grid; gap: var(--sp-3); } /* The folder list: every row the same two tracks, the path cut from the left (its end tells folders apart), the full path in the title. */ .folders { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); } .folders li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; min-height: var(--control-h); padding: 0 0 0 var(--control-px); background: var(--bg); border: var(--border-w) solid var(--border); border-radius: var(--radius); } .folders .path { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; direction: rtl; text-align: left; font: var(--text-sm) var(--font-ui); } .folders .btn { height: calc(var(--control-h) - 2 * var(--border-w)); box-shadow: none; border-width: 0 0 0 var(--border-w); } .folders .empty { padding: var(--control-px); color: var(--warning); font-size: var(--text-sm); } /* --- The viewer ---------------------------------------------------------------------------- */ .viewer { grid-area: viewer; min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); border-left: var(--border-w) solid var(--border); background: var(--bg); } .viewer__head { display: grid; grid-template-columns: minmax(0, 1fr) auto var(--control-h-sm); gap: var(--sp-2); align-items: center; min-height: var(--header-height); padding: 0 var(--sp-3); border-bottom: var(--border-w) solid var(--border); } .viewer__id { min-width: 0; } .viewer__name { font: 600 var(--text-sm) / var(--leading-tight) var(--font-ui); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .viewer__where { font: var(--text-xs) var(--font-ui); color: var(--ink-muted); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .viewer__modes { display: grid; grid-auto-flow: column; } .seg { height: var(--control-h-sm); padding: 0 var(--sp-3); font: var(--text-xs) var(--font-ui); color: var(--ink-muted); background: var(--surface); border: var(--border-w) solid var(--border); cursor: pointer; } .seg + .seg { border-left: 0; } .seg[aria-pressed="true"] { color: var(--ink); background: var(--surface-active); } .viewer__body { min-height: 0; display: grid; } .viewer__code { min-height: 0; overflow: hidden; } .viewer__code .cm-editor { height: 100%; } .viewer__md { overflow: auto; padding: var(--sp-4); } .viewer__frame { width: 100%; height: 100%; border: 0; background: var(--surface); } .viewer__note { padding: var(--sp-4); font-size: var(--text-sm); color: var(--ink-muted); } .viewer__note.is-error { color: var(--warning); } /* --- The activity panel ------------------------------------------------------------------------- Beside the chat, the inspector's width; while the viewer is open too, the viewer goes over the chat (it was opened from here, and three columns of text beside the sidebar do not fit). Over the chat from --bp-wide down, as the viewer is; at --bp-narrow that is a full-height sheet. */ .shell[data-activity="true"], .shell[data-activity="true"][data-viewer="true"] { grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--inspector-width); grid-template-areas: "side main activity"; } .shell[data-activity="true"] .viewer { grid-area: main; z-index: var(--z-panel); border-left: 0; } .activity { grid-area: activity; min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); border-left: var(--border-w) solid var(--border); background: var(--bg); } /* Title and close on two known tracks; with an agent's conversation open, Back before them. */ .activity__head { grid-template-columns: minmax(0, 1fr) var(--control-h-sm); } .activity[data-view="agent"] .activity__head { grid-template-columns: var(--control-h-sm) minmax(0, 1fr) var(--control-h-sm); } .activity__body { overflow: auto; min-height: 0; display: grid; align-content: start; font-size: var(--text-sm); } .activity__section { padding: var(--sp-3); border-bottom: var(--border-w) solid var(--border); min-width: 0; } .activity__section:last-child { border-bottom: 0; } .activity__heading, .activity__subheading { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; margin: 0; font: 600 var(--text-sm) / var(--leading-tight) var(--font-ui); color: var(--ink); cursor: pointer; } .activity__heading::-webkit-details-marker { display: none; } .activity__section[open] > .activity__heading { margin-bottom: var(--sp-3); } .activity__subheading { margin: var(--sp-4) 0 var(--sp-2); cursor: default; } .activity__count { font: var(--text-xs) var(--font-mono); color: var(--ink-muted); } .activity__empty { margin: 0; padding: var(--sp-1) 0; color: var(--ink-faint); font-size: var(--text-sm); } .activity__empty.is-error { color: var(--warning); padding: var(--sp-3); } .activity__plan { min-width: 0; } /* Context: the line, the bar, then one row per category on four fixed tracks -- swatch, the name that gives, and two number columns -- so the numbers stand in columns in any language. The categories' colours are tokens, one each. */ .ctx { display: grid; gap: var(--sp-2); } .ctx__used { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-2); margin: 0; color: var(--ink); } .ctx__of { font-family: var(--font-mono); color: var(--ink-muted); } .ctx__bar { display: flex; height: var(--sp-2); overflow: hidden; background: var(--surface-active); border-radius: var(--radius-full); } .ctx__seg { flex: none; width: var(--share, 0); background: var(--ctx, var(--ink-faint)); } .ctx__rows { display: grid; margin: 0; padding: 0; list-style: none; } .ctx__row { display: grid; grid-template-columns: var(--sp-3) minmax(0, 1fr) var(--num-col) var(--num-col); gap: var(--sp-2); align-items: center; min-height: var(--row-h); } .ctx__key { width: var(--sp-3); height: var(--sp-3); border-radius: var(--radius-sm); background: var(--ctx, var(--ink-faint)); } .ctx--free.ctx__key { background: transparent; border: var(--border-w) solid var(--border-strong); } .ctx__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--ink-muted); } .ctx__num { font: var(--text-xs) var(--font-mono); text-align: right; color: var(--ink-muted); } .ctx__note { margin: 0; font-size: var(--text-xs); color: var(--ink-faint); } .ctx--messages { --ctx: var(--accent); } .ctx--system { --ctx: var(--ink-muted); } .ctx--memory { --ctx: var(--warning); } .ctx--instructions { --ctx: var(--success); } .ctx--tools { --ctx: var(--ink); } .ctx--mcp_tools { --ctx: var(--danger); } .ctx--since { --ctx: var(--ink-faint); } .ctx--buffer { --ctx: var(--border-strong); } .ctx--free { --ctx: transparent; } /* Outputs: icon, the name (cut, never wrapped), the lines added and removed. */ .outs { display: grid; margin: 0; padding: 0; list-style: none; } .outs__row { display: grid; grid-template-columns: var(--sp-4) minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; min-height: var(--row-h); color: var(--ink-muted); } .outs__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0; font: var(--text-sm) var(--font-ui); color: var(--ink); text-align: left; background: none; border: 0; cursor: pointer; } .outs__name:hover { color: var(--accent); text-decoration: underline; } .outs__diff { display: grid; grid-auto-flow: column; gap: var(--sp-2); font: var(--text-xs) var(--font-mono); } .outs__add { color: var(--success); } .outs__del { color: var(--danger); } /* Background tasks. An agent's row is one grid of known tracks: state dot, what it is (the one track that gives, cut), elapsed time in a column of its own width, the stop button at its size (an empty box where there is none) -- so rows line up whatever each says. */ .tasks { display: grid; gap: var(--sp-2); min-width: 0; } .tasks__summary, .tasks__team { margin: 0; color: var(--ink-muted); } .tasks__goal { margin: 0; color: var(--ink); } .tasks__list { display: grid; gap: var(--sp-1); } .tasks__more > summary { cursor: pointer; padding: var(--sp-1) 0; color: var(--ink-muted); } .tasks__more[open] > summary { margin-bottom: var(--sp-1); } .agent { margin-left: calc(var(--depth, 0) * var(--sp-4)); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); min-width: 0; } .agent__row { display: grid; grid-template-columns: var(--dot-size) minmax(0, 1fr) var(--time-col) var(--control-h-sm); gap: var(--sp-2); align-items: center; min-height: var(--control-h); padding: 0 var(--sp-1) 0 var(--sp-3); cursor: pointer; list-style: none; } .agent__row::-webkit-details-marker { display: none; } .agent__dot { width: var(--dot-size); height: var(--dot-size); border-radius: var(--radius-full); background: var(--ink-faint); } .agent.is-working .agent__dot { background: var(--accent); } .agent.is-queued .agent__dot, .agent.is-waiting .agent__dot { background: var(--warning); } .agent.is-done .agent__dot { background: var(--leaf); } .agent.is-error .agent__dot { background: var(--danger); } .agent__what { display: grid; min-width: 0; } .agent__name, .agent__role { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .agent__name { color: var(--ink); } .agent__role { font-size: var(--text-xs); color: var(--ink-muted); } .agent__time { font: var(--text-xs) var(--font-mono); text-align: right; color: var(--ink-muted); } .agent__stop { width: var(--control-h-sm); height: var(--control-h-sm); } .agent__body { display: grid; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3) var(--sp-3); border-top: var(--border-w) solid var(--border); min-width: 0; } .agent__body > .btn { justify-self: start; } .agent__facts { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); margin: 0; font-size: var(--text-xs); color: var(--ink-muted); } .agent__state { color: var(--ink); } .agent__model { font-family: var(--font-mono); overflow-wrap: anywhere; } .agent__brief { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink); } .agent__step { display: grid; grid-template-columns: var(--dot-size) auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; margin: 0; } .agent__verb { color: var(--ink); white-space: nowrap; } .agent__title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--text-xs) var(--font-mono); color: var(--ink-muted); } .agent__text { margin: 0; max-height: calc(6 * var(--row-h)); overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--text-xs); color: var(--ink-muted); } /* The team's room: who to whom, a report marked, the words as markdown. */ .room { display: grid; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; } .room__entry { display: grid; gap: var(--sp-1); padding: var(--sp-2) var(--sp-3); background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); min-width: 0; } .room__entry.is-report { border-left: var(--border-w-thick) solid var(--leaf); } .room__meta { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; font-size: var(--text-xs); color: var(--ink-muted); } .room__n { font-family: var(--font-mono); } .room__route { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .room__badge { color: var(--leaf); border-color: var(--leaf); } /* One agent's conversation, read-only. */ .convo__head { display: grid; gap: var(--sp-2); padding: var(--sp-3); border-bottom: var(--border-w) solid var(--border); } .convo__head > .btn { justify-self: start; } .convo { display: grid; gap: var(--sp-3); padding: var(--sp-3); min-width: 0; } .convo__turn { font-size: var(--text-sm); } .convo__tools { display: grid; gap: var(--sp-1); margin: var(--sp-2) 0 0; padding: 0; list-style: none; } .convo__tool { display: grid; grid-template-columns: var(--dot-size) auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; font-size: var(--text-xs); } /* The strip above the message box: what the agents are doing, one line, and the way into the panel. */ .strip { padding: var(--sp-2) var(--sp-4) 0; } .strip__btn { display: grid; grid-template-columns: var(--dot-size) minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center; width: 100%; max-width: var(--thread-max-width); min-height: var(--control-h); margin: 0 auto; padding: 0 var(--control-px-sm); font: var(--text-sm) var(--font-ui); color: var(--ink-muted); text-align: left; background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius); cursor: pointer; } .strip__btn:hover { color: var(--ink); background: var(--surface-hover); } .strip__text { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } /* --- Menus, dialogs and the palette ----------------------------------------------------------- */ .menu { position: fixed; z-index: var(--z-dropdown); min-width: 12rem; max-width: min(var(--w-menu), calc(100vw - 2 * var(--sp-2))); max-height: min(var(--h-list), calc(100vh - 2 * var(--sp-2))); overflow: auto; padding: var(--sp-1) 0; background: var(--surface-raised); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg); } /* Every item: lead · label · check, on the same tracks, so labels line up with or without a lead. */ .menu__item { display: grid; grid-template-columns: 1.25rem minmax(0, 1fr) 1rem; gap: var(--sp-2); align-items: center; width: 100%; min-height: var(--row-h); padding: 0 var(--sp-3); font: var(--text-sm) var(--font-ui); color: var(--ink); text-align: left; background: none; border: 0; cursor: pointer; } /* A menu where no item has a lead: no lead track either. */ .menu--plain .menu__item { grid-template-columns: minmax(0, 1fr) 1rem; } .menu--plain .menu__lead { display: none; } .menu__item:hover, .menu__item:focus-visible { background: var(--surface-hover); outline: none; } .menu__item:disabled { opacity: var(--opacity-dim); cursor: default; } .menu__item.is-danger { color: var(--danger); } .menu__label { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .menu__check { color: var(--accent); } .menu__sep { height: var(--border-w); margin: var(--sp-1) 0; background: var(--border); } .dialog { width: min(var(--w-dialog), calc(100vw - 2 * var(--sp-4))); padding: 0; color: var(--ink); background: var(--surface-raised); border: var(--border-w) solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg); } .dialog::backdrop { background: var(--scrim); } .dialog__body { display: grid; gap: var(--sp-3); padding: var(--sp-4); } .dialog__title { font: 600 var(--text-md) / var(--leading-tight) var(--font-ui); } /* A line to copy: as it is, on one line that scrolls on its own rather than the dialog. */ .dialog__code { margin: 0; padding: var(--sp-2) var(--sp-3); overflow-x: auto; white-space: pre; font: var(--text-sm) var(--font-mono); color: var(--ink); background: var(--code-bg); border: var(--border-w) solid var(--code-border); border-radius: var(--radius); user-select: all; } .dialog__input { width: 100%; } .dialog__actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); } .palette { align-self: start; margin-top: 12vh; } .palette__line { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-2); align-items: center; padding: 0 var(--sp-3); border-bottom: var(--border-w) solid var(--border); color: var(--ink-muted); } .palette__input { height: var(--control-h-lg) !important; border: 0 !important; background: none !important; outline: none; font-size: var(--text-base); } .palette__list { list-style: none; margin: 0; padding: var(--sp-1) 0; max-height: var(--h-list); overflow: auto; } /* A result: icon · label · hint, the same tracks on every row. */ .palette__item { display: grid; grid-template-columns: 1rem minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; min-height: var(--row-h); padding: 0 var(--sp-3); font: var(--text-sm) var(--font-ui); cursor: pointer; } .palette__item[aria-selected="true"] { background: var(--surface-active); } .palette__icon { display: grid; place-items: center; color: var(--ink-muted); } .palette__label { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .palette__hint { font-size: var(--text-xs); color: var(--ink-faint); white-space: nowrap; } .palette__none { padding: var(--sp-3); font-size: var(--text-sm); color: var(--ink-muted); } /* --- Narrower windows ---------------------------------------------------------------------- */ /* 64rem (--bp-wide): the viewer goes over the chat instead of beside it. */ @media (max-width: 64rem) { .shell[data-viewer="true"] { grid-template-columns: var(--sidebar-width) minmax(0, 1fr); grid-template-areas: "side main"; } .viewer { grid-area: main; z-index: var(--z-panel); border-left: 0; } .shell[data-activity="true"], .shell[data-activity="true"][data-viewer="true"] { grid-template-columns: var(--sidebar-width) minmax(0, 1fr); grid-template-areas: "side main"; } .activity { grid-area: main; z-index: var(--z-panel); border-left: 0; } } /* 48rem (--bp-narrow): the sidebar is a drawer, opened from the title bar. */ @media (max-width: 48rem) { :root { --side-btn-w: var(--titlebar-h); } .bar__side { visibility: visible; } .bar__host { display: none; } .shell, .shell[data-viewer="true"], .shell[data-activity="true"], .shell[data-activity="true"][data-viewer="true"] { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main"; } .side { position: absolute; inset: 0 auto 0 0; width: min(85vw, var(--sidebar-width)); z-index: var(--z-panel); transform: translateX(-100%); transition: transform var(--dur-2) var(--ease-out); box-shadow: var(--shadow-lg); } .shell[data-side="true"] .side { transform: none; } .shell[data-side="true"] .scrim { display: block; position: absolute; inset: 0; z-index: calc(var(--z-panel) - 1); background: var(--scrim); } .viewer { z-index: var(--z-panel); } .head { padding: var(--sp-2) var(--sp-3) 0; grid-template-columns: minmax(0, 1fr) auto; } .head__place { grid-column: 1 / -1; grid-row: 2; padding-bottom: var(--sp-2); } /* The chat's controls get a row of their own: beside the title they would squeeze it out. */ .head__tools { grid-column: 1 / -1; grid-row: 3; flex-wrap: wrap; padding-bottom: var(--sp-2); } .head__tools:empty { display: none; } .thread { padding: var(--sp-3); } .composer { padding: var(--sp-2) var(--sp-3) var(--sp-3); } .strip { padding: var(--sp-2) var(--sp-3) 0; } .cards { padding: var(--sp-2) var(--sp-3) 0; } .card { padding: var(--sp-4); gap: var(--sp-4); } .msg--user { max-width: 100%; } .palette__hint { display: none; } .palette__item { grid-template-columns: 1rem minmax(0, 1fr); } .head__model .picker { max-width: 8rem; } } /* Very narrow: the agent's words go, its dot stays; the row's button goes under its field. */ @media (max-width: 30rem) { #agent-text { display: none; } .setup .row { grid-template-columns: minmax(0, 1fr); } .setup .field { grid-template-rows: auto auto auto; } }