/* components.css — the §5.2 inventory. Class names are binding.
 * Cascade position: third. Defines no custom property, no literal colour.
 * Every state is keyed off a real attribute (:disabled, [aria-busy],
 * [aria-expanded], [aria-selected], [data-…]) so JS never toggles a style class
 * that CSS alone could have expressed.
 */

/* ══ keyframes ═════════════════════════════════════════════════════════════ */

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(0.72);
  }

  50% {
    transform: scale(1);
  }
}

@keyframes shimmer {
  to {
    background-position-x: -200%;
  }
}

@keyframes sheet-in {
  from {
    transform: translateY(16px);
  }
}

@keyframes drawer-in {
  from {
    transform: translateX(16px);
  }
}

/* ══ button ════════════════════════════════════════════════════════════════ */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: 36px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base);
  font-weight: var(--fw-medium);
  line-height: var(--lh-tight);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}

.btn:hover {
  background: var(--surface-hover);
}

.btn:active {
  background: var(--bg-inset);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  background: var(--bg-subtle);
  border-color: var(--border);
  color: var(--text-faint);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

.btn--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.btn--primary:active {
  background: var(--accent-hover);
}

.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  background: var(--bg-inset);
  border-color: var(--border);
  color: var(--text-faint);
}

.btn--secondary {
  background: var(--bg-subtle);
  border-color: var(--border-strong);
  color: var(--text);
}

.btn--secondary:hover {
  background: var(--bg-inset);
}

.btn--ghost {
  background: none;
  border-color: transparent;
  color: var(--text-muted);
  padding-inline: var(--sp-2);
}

.btn--ghost:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.btn--ghost:disabled {
  background: none;
  border-color: transparent;
}

/* a text action that starts a line: the invisible box gives up its start
   padding, so the label lines up with the column above it instead of 8 px in */
.btn--inline {
  margin-inline-start: calc(-1 * var(--sp-2));
}

.btn--danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-fg);
}

/* there is no --danger-hover token, and inventing one would break the §5.1
   palette; a small brightness lift reads as "hover" in both themes */
.btn--danger:hover {
  filter: brightness(1.12);
}

.btn--danger:disabled {
  background: var(--bg-inset);
  border-color: var(--border);
  color: var(--text-faint);
}

.btn--icon {
  inline-size: 36px;
  padding: 0;
  flex: none;
}

/* Disabled looks disabled, for every variant and theme: in dark a disabled
   primary was a solid sunken button ("Connect" looked pressable), and a
   disabled ghost only swapped two greys nobody can tell apart. The label is a
   step below the faintest live text (--text-faint is 4.5:1 for timestamps);
   WCAG 1.4.3 exempts it, and tests/cases/a11y.js applies exactly that
   exemption. A busy button keeps its spinner look. */
.btn:disabled:not([aria-busy="true"]),
.btn[aria-disabled="true"]:not([aria-busy="true"]) {
  background: var(--bg-subtle);
  border-color: var(--border);
  color: var(--border-strong);
  box-shadow: none;
  filter: none;
  cursor: not-allowed;
}

.btn--ghost:disabled:not([aria-busy="true"]),
.btn--ghost[aria-disabled="true"]:not([aria-busy="true"]) {
  background: transparent;
  border-color: transparent;
}

.btn--block {
  inline-size: 100%;
}

/* busy: the label stays in place (width locked) and a spinner sits over it */
.btn[aria-busy="true"] {
  cursor: progress;
  color: transparent;
}

.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 1em;
  block-size: 1em;
  margin-block-start: -0.5em;
  margin-inline-start: -0.5em;
  border: 2px solid var(--border-strong);
  border-block-start-color: var(--text);
  border-radius: var(--r-full);
  animation: spin 700ms linear infinite;
}

.btn--primary[aria-busy="true"]::after {
  border-color: var(--accent-hover);
  border-block-start-color: var(--accent-fg);
}

.btn--danger[aria-busy="true"]::after {
  border-color: var(--danger);
  border-block-start-color: var(--danger-fg);
}

/* a danger button that is still arming: inert, with the delay drawn */
.btn[data-arm] {
  cursor: progress;
  overflow: hidden;
}

.btn[data-arm]::before {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  block-size: 2px;
  background: currentColor;
  animation: arming calc(var(--dur-slow) + var(--dur-fast)) linear forwards;
}

@keyframes arming {
  from {
    inline-size: 0;
  }

  to {
    inline-size: 100%;
  }
}

.spinner {
  display: inline-block;
  inline-size: 1em;
  block-size: 1em;
  flex: none;
  border: 2px solid var(--border-strong);
  border-block-start-color: currentColor;
  border-radius: var(--r-full);
  animation: spin 700ms linear infinite;
}

/* ══ dot ═══════════════════════════════════════════════════════════════════ */

.dot {
  inline-size: 8px;
  block-size: 8px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--text-faint);
}

.dot--pulse {
  background: var(--accent);
  animation: pulse 1.4s var(--ease-in-out) infinite;
}

/* ══ field ═════════════════════════════════════════════════════════════════ */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-inline-size: 0;
}

.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
}

.field__input {
  inline-size: 100%;
  min-block-size: 36px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  transition:
    border-color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.field__input::placeholder {
  color: var(--text-faint);
}

.field__input:hover {
  border-color: var(--text-faint);
}

.field__input:disabled {
  background: var(--bg-subtle);
  color: var(--text-faint);
  cursor: not-allowed;
}

.field__input[readonly] {
  background: var(--bg-subtle);
  color: var(--text-muted);
}

.field__input[aria-invalid="true"] {
  border-color: var(--danger);
  background: var(--danger-subtle);
}

/* a field that failed keeps its colour while focused: the green focus ring
   round a red box read as "this one is fine" */
.field__input[aria-invalid="true"]:focus-visible {
  outline-color: var(--danger);
}

.field__hint {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.field__err {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--danger);
}

.field__count {
  align-self: flex-end;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}

.field__count[data-level="near"] {
  color: var(--warn);
}

.field__count[data-level="over"] {
  color: var(--danger);
  font-weight: var(--fw-semibold);
}

.field--textarea .field__input {
  min-block-size: calc(var(--rows) * 1lh + var(--sp-4));
  line-height: var(--lh-base);
  resize: vertical;
}

/* password + its reveal toggle share one bordered box */
.field--password .field__box,
.field--search .field__box {
  display: flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
}

.field--password .field__box:focus-within,
.field--search .field__box:focus-within {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.field--password .field__box .field__input,
.field--search .field__box .field__input {
  border: 0;
  background: none;
  flex: 1 1 auto;
  min-inline-size: 0;
}

.field--password .field__box .field__input:focus-visible,
.field--search .field__box .field__input:focus-visible {
  outline: none;
}

/* when the reveal button is the focused element it carries the ring, not the
   box around it — one ring, on the thing the keyboard is actually on */
.field--password .field__box:has(.field__reveal:focus-visible),
.field--search .field__box:has(.field__reveal:focus-visible) {
  outline: none;
}

/* the shared box is what shows the field, so it is the box that goes red —
   and its ring with it, the same as a plain invalid field's */
.field--password .field__box:has(.field__input[aria-invalid="true"]),
.field--search .field__box:has(.field__input[aria-invalid="true"]) {
  border-color: var(--danger);
  background: var(--danger-subtle);
}

.field--password .field__box:has(.field__input[aria-invalid="true"]:focus),
.field--search .field__box:has(.field__input[aria-invalid="true"]:focus) {
  outline-color: var(--danger);
}

.field__reveal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 34px;
  block-size: 34px;
  flex: none;
  margin-inline-end: 2px;
  border-radius: var(--r-sm);
  color: var(--text-muted);
}

.field__reveal:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.field__reveal[aria-pressed="true"] {
  color: var(--accent);
}

/* select: native control, chevron drawn from borders so no asset is needed */
.field--select .field__box {
  position: relative;
  display: block;
}

.field--select .field__input {
  appearance: none;
  padding-inline-end: var(--sp-6);
  cursor: pointer;
}

.field--select .field__box::after {
  content: "";
  position: absolute;
  inset-inline-end: var(--sp-3);
  inset-block-start: calc(50% - 5px);
  inline-size: 7px;
  block-size: 7px;
  border-inline-end: 1.5px solid var(--text-muted);
  border-block-end: 1.5px solid var(--text-muted);
  transform: rotate(45deg);
  pointer-events: none;
}

/* check / radio / switch: a row, label to the right, whole row is the target */
.field--check,
.field--radio,
.field--switch {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--sp-3);
  min-block-size: var(--tap);
  padding-block: var(--sp-2);
}

.field--check .field__label,
.field--radio .field__label,
.field--switch .field__label {
  font-size: var(--fs-base);
  font-weight: var(--fw-normal);
  cursor: pointer;
}

.field--switch {
  justify-content: space-between;
}

.field--switch .field__label {
  order: -1;
}

input[type="checkbox"].field__input,
input[type="radio"].field__input {
  appearance: none;
  inline-size: 20px;
  block-size: 20px;
  min-block-size: 0;
  flex: none;
  margin-block-start: 2px;
  padding: 0;
  border: 1.5px solid var(--border-strong);
  background: var(--surface);
  cursor: pointer;
}

input[type="radio"].field__input {
  border-radius: var(--r-full);
}

input[type="checkbox"].field__input {
  border-radius: var(--r-sm);
}

input[type="checkbox"].field__input:checked,
input[type="radio"].field__input:checked {
  border-color: var(--accent);
  background: var(--accent);
}

input[type="checkbox"].field__input:checked::after {
  content: "";
  display: block;
  inline-size: 5px;
  block-size: 10px;
  margin: 1px auto 0;
  border-inline-end: 2px solid var(--accent-fg);
  border-block-end: 2px solid var(--accent-fg);
  transform: rotate(42deg);
}

input[type="radio"].field__input:checked::after {
  content: "";
  display: block;
  inline-size: 8px;
  block-size: 8px;
  margin: 4px auto;
  border-radius: var(--r-full);
  background: var(--accent-fg);
}

input[type="checkbox"].field__input:disabled,
input[type="radio"].field__input:disabled {
  border-color: var(--border);
  background: var(--bg-inset);
  cursor: not-allowed;
}

input[type="checkbox"].field__input:checked:disabled {
  background: var(--border-strong);
}

input[type="checkbox"].field__input[aria-invalid="true"],
input[type="radio"].field__input[aria-invalid="true"] {
  border-color: var(--danger);
}

/* Forced colours: these inputs are drawn by their FILL (appearance: none), and
   the browser forces every background to Canvas — so a checked radio, a checked
   box and an ON switch all painted as empty. They opt out of the repaint and
   draw with the system colours tokens.css hands them under the same query. */
@media (forced-colors: active) {
  input[type="checkbox"].field__input,
  input[type="radio"].field__input {
    forced-color-adjust: none;
  }
}

/* switch: the same checkbox, drawn as a track */
.field--switch .field__input[type="checkbox"] {
  inline-size: 40px;
  block-size: 24px;
  margin-block-start: 0;
  border-radius: var(--r-full);
  background: var(--bg-inset);
  border-color: var(--border-strong);
  transition:
    background var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

/* both states are listed so this beats the checkbox tick rule above, which is
   more specific in the :checked state and would otherwise shape the knob */
.field--switch .field__input[type="checkbox"]::after,
.field--switch .field__input[type="checkbox"]:checked::after {
  content: "";
  display: block;
  inline-size: 16px;
  block-size: 16px;
  margin: 2px;
  border: 0;
  border-radius: var(--r-full);
  background: var(--text-muted);
  transform: none;
  transition:
    transform var(--dur-base) var(--ease-out),
    background var(--dur-base) var(--ease-out);
}

.field--switch .field__input[type="checkbox"]:checked {
  background: var(--accent);
  border-color: var(--accent);
}

.field--switch .field__input[type="checkbox"]:checked::after {
  background: var(--accent-fg);
  transform: translateX(16px);
}

.field--switch .field__input[type="checkbox"]:disabled::after {
  background: var(--text-faint);
}

/* a radio/checkbox group that carries its own explanation per option */
.choices {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.choice {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  align-items: start;
  gap: var(--sp-1) var(--sp-3);
  min-block-size: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
}

.choice:hover {
  background: var(--surface-hover);
}

.choice:has(:checked) {
  border-color: var(--accent);
  background: var(--accent-subtle);
}

.choice:focus-within {
  border-color: var(--focus);
}

.choice__label {
  font-weight: var(--fw-medium);
}

.choice__hint {
  grid-column: 2;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.choice__slot {
  grid-column: 2;
  padding-block-start: var(--sp-2);
}

/* ══ chips input ═══════════════════════════════════════════════════════════ */

.chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: 36px;
  padding: var(--sp-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
}

.chips:focus-within {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.chips__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-1) 2px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  font-size: var(--fs-sm);
}

.chips--glob .chips__chip,
.chips--command .chips__chip {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}

.chips--tag .chips__chip {
  border-radius: var(--r-full);
  padding-inline-start: var(--sp-3);
}

.chips__chip[data-invalid] {
  border-color: var(--danger);
  background: var(--danger-subtle);
  color: var(--danger);
}

.chips__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 24px;
  block-size: 24px;
  flex: none;
  border-radius: var(--r-sm);
  color: var(--text-muted);
}

.chips__remove:hover {
  background: var(--danger-subtle);
  color: var(--danger);
}

.chips__add {
  flex: 1 1 8ch;
  min-inline-size: 8ch;
  min-block-size: 24px;
  border: 0;
  background: none;
  color: var(--text);
  font-size: var(--fs-sm);
}

.chips__add:focus-visible {
  outline: none;
}

.chips__add::placeholder {
  color: var(--text-faint);
}

/* ══ key / value rows ══════════════════════════════════════════════════════ */

.kv {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-inline-size: 0;
}

.kv__row {
  display: grid;
  grid-template-columns: minmax(12ch, 30%) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) 0;
  border-block-end: 1px solid var(--border);
}

.kv__row:last-child {
  border-block-end: 0;
}

.kv__key {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.kv__val {
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}

.kv--env .kv__key,
.kv--header .kv__key {
  color: var(--text);
  font-weight: var(--fw-medium);
}

.kv__row[data-masked] .kv__val {
  font-family: var(--font-mono);
  color: var(--text-faint);
  letter-spacing: 0.08em;
  user-select: none;
}

/* ══ tool definitions (lib/tooldefs.js) ════════════════════════════════════
 * One disclosure per tool a turn would send: the name is the button, the
 * description and the input schema sit behind it. Open state is the button's
 * own aria-expanded; the body is toggled with `hidden`. */

.tooldefs {
  list-style: none;
  margin: 0;
  padding: 0;
  min-inline-size: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}

.tooldefs__item + .tooldefs__item {
  border-block-start: 1px solid var(--border);
}

.tooldefs__toggle {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--sp-2);
  inline-size: 100%;
  min-block-size: var(--tap);
  padding: var(--sp-1) var(--sp-3);
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.tooldefs__toggle:hover {
  background: var(--surface-hover);
}

.tooldefs__toggle::before {
  content: "▸";
  color: var(--text-faint);
  font-size: var(--fs-xs);
  transition: transform var(--dur-fast) var(--ease-out);
}

.tooldefs__toggle[aria-expanded="true"]::before {
  transform: rotate(90deg);
}

.tooldefs__names {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  min-inline-size: 0;
}

/* a long MCP tool name wraps instead of ending in an ellipsis */
.tooldefs__names .chip--mono {
  color: var(--text);
  white-space: normal;
  overflow-wrap: anywhere;
  border-radius: var(--r-sm);
}

.tooldefs__body {
  padding: 0 var(--sp-3) var(--sp-3);
  min-inline-size: 0;
}

.tooldefs__facts {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin: 0;
  min-inline-size: 0;
}

.tooldefs__term {
  margin-block-start: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.tooldefs__facts dd {
  margin: 0;
  min-inline-size: 0;
}

.tooldefs__desc {
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text);
}

/* wraps rather than scrolls sideways: the column is ~340 px and a scroller
   nobody can focus hides the end of every long "description" */
.tooldefs__schema {
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--code-border);
  border-radius: var(--r-sm);
  background: var(--code-bg);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: var(--lh-base);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* fact rows (the inspector's reasoning policy): key | value + source chip */
.kv--facts .kv__row {
  grid-template-columns: minmax(10ch, 38%) minmax(0, 1fr);
}

.kv__vals {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  min-inline-size: 0;
}

/* "agent:<slug>" is as long as the slug: wrap it rather than cut it off */
.kv__vals .chip {
  white-space: normal;
  overflow-wrap: anywhere;
  border-radius: var(--r-sm);
}

@media (max-width: 560px) {
  .kv--facts .kv__row {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 560px) {
  .kv__row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .kv__key {
    grid-column: 1 / -1;
  }
}

/* ══ card ══════════════════════════════════════════════════════════════════ */

.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--sh-1);
  min-inline-size: 0;
}

.card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

.card__title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  margin: 0;
}

.card__body {
  min-inline-size: 0;
}

.card__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding-block-start: var(--sp-1);
}

.card--interactive {
  cursor: pointer;
  text-align: start;
  transition:
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}

.card--interactive:hover {
  border-color: var(--border-strong);
  box-shadow: var(--sh-2);
}

.card--interactive:focus-within {
  border-color: var(--focus);
}

.card--selected {
  border-color: var(--accent);
  background: var(--accent-subtle);
}

.card--danger {
  border-color: var(--danger);
  background: var(--danger-subtle);
}

.card[data-drag] {
  border-style: dashed;
  border-color: var(--accent);
  background: var(--accent-subtle);
}

/* a row of cards that share it: equal shares from one basis, so a long title
   wraps inside its card instead of pushing the card onto a row of its own,
   and every card in the row is as tall as the tallest */
.card-row {
  align-items: stretch;
}

.card-row > .card {
  flex: 1 1 12rem;
}

/* ══ dialog ════════════════════════════════════════════════════════════════ */

.dialog {
  /* a modal <dialog> is promoted to the top layer and needs no z-index; this is
     for the non-modal case, where it is an ordinary absolutely-positioned box */
  z-index: var(--z-dialog);
  inline-size: min(560px, calc(100vw - 2 * var(--sp-4)));
  /* Chrome's UA sheet caps a modal at calc(100% - 6px - 2em); restate the caps
     we want or the sheet/drawer variants silently come up short. */
  max-inline-size: min(560px, calc(100vw - 2 * var(--sp-4)));
  max-block-size: min(80vh, 720px);
  margin: auto;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--sh-3);
  overflow: hidden;
}

.dialog::backdrop {
  background: var(--scrim);
}

.dialog[open] {
  display: flex;
  flex-direction: column;
  animation: sheet-in var(--dur-base) var(--ease-out);
}

.dialog__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-block-end: 1px solid var(--border);
}

.dialog__title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
}

.dialog__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  flex: none;
  margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) 0;
  border-radius: var(--r-md);
  color: var(--text-muted);
}

.dialog__close:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.dialog__body {
  padding: var(--sp-4);
  overflow-y: auto;
  flex: 1 1 auto;
  min-block-size: 0;
}

.dialog__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4);
  border-block-start: 1px solid var(--border);
  background: var(--bg-subtle);
}

/* a bottom sheet: the mobile presentation, and the narrow inspector */
.dialog--sheet {
  inline-size: 100vw;
  max-inline-size: 100vw;
  max-block-size: 80vh;
  margin: auto auto 0;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  border-block-end: 0;
  padding-block-end: env(safe-area-inset-bottom);
}

/* a side drawer: the medium-width inspector, the narrow rail, Run once */
.dialog--drawer {
  block-size: 100dvh;
  max-block-size: 100dvh;
  inline-size: min(var(--inspector-w), calc(100vw - var(--sp-7)));
  max-inline-size: none;
  margin: 0 0 0 auto;
  border-radius: var(--r-xl) 0 0 var(--r-xl);
  border-inline-end: 0;
}

.dialog--drawer[open] {
  animation: drawer-in var(--dur-base) var(--ease-out);
}

.dialog--drawer[data-side="start"] {
  inline-size: min(var(--rail-w), calc(100vw - var(--sp-7)));
  margin: 0 auto 0 0;
  border-radius: 0 var(--r-xl) var(--r-xl) 0;
  border-inline-start: 0;
  border-inline-end: 1px solid var(--border);
}

/* non-dismissible: the once-only API key. No close button, no backdrop exit. */
.dialog--sticky::backdrop {
  background: var(--scrim);
}

.dialog--sticky .dialog__close {
  display: none;
}

/* narrow: a plain dialog becomes a bottom sheet. The two variants that already
   declare their own geometry are excluded, or this later rule would undo them. */
@media (max-width: 560px) {
  .dialog:not(.dialog--sheet):not(.dialog--drawer) {
    inline-size: 100vw;
    max-inline-size: 100vw;
    max-block-size: 88vh;
    margin: auto auto 0;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-inline: 0;
    border-block-end: 0;
    padding-block-end: env(safe-area-inset-bottom);
  }
}

/* ══ popover / coach mark ══════════════════════════════════════════════════
 * Anchored by script, which may only write --pop-x / --pop-y (§5.4 rule 4).
 */

.pop {
  position: fixed;
  inset: auto auto auto 0;
  inset-block-start: var(--pop-y);
  inset-inline-start: var(--pop-x);
  inline-size: min(380px, calc(100vw - 2 * var(--sp-4)));
  max-block-size: 70vh;
  margin: 0;
  padding: var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--sh-2);
  overflow-y: auto;
}

.pop::backdrop {
  background: none;
}

.pop[open] {
  display: block;
  animation: sheet-in var(--dur-fast) var(--ease-out);
}

.pop__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-block-end: var(--sp-3);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
}

.pop__body {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.pop__body p + p {
  margin-block-start: var(--sp-2);
}

/* a row's … menu (rail.js): as wide as its items, no head — it opens beside
   the title it acts on.  Its width is rail.js MENU_WIDTH. */
.pop--menu {
  inline-size: min(200px, calc(100vw - 2 * var(--sp-4)));
  padding: var(--sp-1);
}

.pop--menu .pop__body {
  display: flex;
  flex-direction: column;
  color: var(--text);
}

.pop--menu .rail__item:not(.rail__danger) {
  color: var(--text);
}

.pop--menu .pop__body > p {
  padding: var(--sp-1) var(--sp-2) var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* the menu's title, shown only where the menu is a sheet far from its row */
.pop__caption {
  display: none;
}

/* the numbered provenance rows of the "Why was this allowed?" popover */
.pop__row {
  display: grid;
  grid-template-columns: 1.4em minmax(10ch, 1fr) minmax(0, 1.4fr) auto;
  align-items: baseline;
  gap: var(--sp-2);
  padding-block: var(--sp-2);
  border-block-end: 1px solid var(--border);
  font-size: var(--fs-sm);
}

.pop__row:last-of-type {
  border-block-end: 0;
}

.pop__n {
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.pop__layer {
  color: var(--text-muted);
}

.pop__value {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  overflow-wrap: anywhere;
}

/* the row's deep link into the setting that decided it */
.pop__go {
  justify-self: end;
  white-space: nowrap;
  font-size: var(--fs-sm);
}

.pop__said {
  margin-block-start: var(--sp-3);
  padding: var(--sp-3);
  border-inline-start: 3px solid var(--danger);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--danger-subtle);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

@media (max-width: 560px) {
  /* a popover with no room to be anchored becomes a bottom sheet, and a sheet
     needs a scrim: at this width it is a layer, not an annotation */
  .pop {
    inset-block: auto 0;
    inset-inline: 0;
    inline-size: 100vw;
    max-inline-size: 100vw;
    max-block-size: 70vh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-inline: 0;
    border-block-end: 0;
    padding-block-end: max(var(--sp-4), env(safe-area-inset-bottom));
    box-shadow: var(--sh-3);
  }

  .pop::backdrop {
    background: var(--scrim);
  }

  .pop__row {
    grid-template-columns: 1.4em minmax(0, 1fr);
  }

  .pop__value,
  .pop__go {
    grid-column: 2;
  }

  .pop__go {
    justify-self: start;
  }

  .pop--menu {
    padding: var(--sp-3) var(--sp-2) max(var(--sp-4), env(safe-area-inset-bottom));
  }

  .pop__caption {
    display: block;
    padding: 0 var(--sp-2) var(--sp-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-muted);
  }

  .pop--menu .rail__item {
    font-size: var(--fs-base);
  }
}

/*
 * A coach mark is an ANNOTATION, and an annotation must not take the click
 * meant for the thing it annotates. It is positioned over the transcript by
 * construction — §4.11 puts it under the block it explains, and the answer,
 * the "Copy answer" button or the rail can be under it — so the box itself is
 * transparent to the pointer and only its own controls are not. Keyboard
 * reach is untouched: pointer-events has no effect on focus order.
 */
.coach {
  position: fixed;
  pointer-events: none;
  z-index: var(--z-drawer);
  inset-block-start: var(--pop-y);
  inset-inline-start: var(--pop-x);
  inline-size: min(320px, calc(100vw - 2 * var(--sp-4)));
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--r-lg);
  background: var(--accent-subtle);
  color: var(--text);
  box-shadow: var(--sh-2);
}

.coach__body {
  font-size: var(--fs-sm);
  flex: 1 1 auto;
}

.coach button {
  pointer-events: auto;
}

/* the nudge's one action ("Turn it on"): its own line, as wide as its label,
   starting where the sentence above starts (.btn--inline) */
.coach__action {
  display: flex;
  inline-size: fit-content;
  margin-block-start: var(--sp-1);
}

.coach__dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 28px;
  block-size: 28px;
  flex: none;
  border-radius: var(--r-sm);
  color: var(--text-muted);
}

.coach__dismiss:hover {
  background: var(--surface-hover);
  color: var(--text);
}

/* ══ toast ═════════════════════════════════════════════════════════════════ */

/* top-end, not bottom-end: the bottom of every screen is already taken by the
   composer or the settings save bar, and a toast must never cover Send */
.toasts {
  position: fixed;
  z-index: var(--z-toast);
  inset-block-start: calc(var(--header-h) + var(--sp-3));
  inset-inline: auto var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  inline-size: min(400px, calc(100vw - 2 * var(--sp-4)));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-strong);
  border-inline-start-width: 3px;
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--sh-2);
  font-size: var(--fs-sm);
  pointer-events: auto;
  animation: sheet-in var(--dur-base) var(--ease-out);
}

.toast[data-state="leaving"] {
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-in-out);
}

.toast__icon {
  flex: none;
  margin-block-start: 1px;
  color: var(--text-muted);
}

.toast__body {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.toast__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 28px;
  block-size: 28px;
  flex: none;
  margin: -2px calc(-1 * var(--sp-2)) 0 0;
  border-radius: var(--r-sm);
  color: var(--text-muted);
}

.toast__close:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.toast--info {
  border-inline-start-color: var(--info);
}

.toast--info .toast__icon {
  color: var(--info);
}

.toast--ok {
  border-inline-start-color: var(--ok);
}

.toast--ok .toast__icon {
  color: var(--ok);
}

.toast--warn {
  border-inline-start-color: var(--warn);
}

.toast--warn .toast__icon {
  color: var(--warn);
}

.toast--error {
  border-inline-start-color: var(--danger);
  background: var(--danger-subtle);
}

.toast--error .toast__icon {
  color: var(--danger);
}

@media (max-width: 560px) {
  .toasts {
    inset-inline: var(--sp-4);
    inline-size: auto;
  }
}

/* ══ chip / badge ══════════════════════════════════════════════════════════ */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  max-inline-size: 100%;
  padding: 1px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: var(--lh-base);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip svg {
  inline-size: 1em;
  block-size: 1em;
}

.chip--mono {
  font-family: var(--font-mono);
  font-weight: var(--fw-normal);
}

.chip--ok {
  border-color: var(--ok);
  background: var(--ok-subtle);
  color: var(--ok);
}

.chip--warn {
  border-color: var(--warn);
  background: var(--warn-subtle);
  color: var(--warn);
}

.chip--danger {
  border-color: var(--danger);
  background: var(--danger-subtle);
  color: var(--danger);
}

.chip--info {
  border-color: var(--info);
  background: var(--info-subtle);
  color: var(--info);
}

.chip--muted {
  border-color: var(--border);
  background: var(--bg-inset);
  color: var(--text-faint);
}

/* a stop reason: raw and greppable, so monospace and never coloured alone */
.chip--stop {
  font-family: var(--font-mono);
  font-weight: var(--fw-normal);
  border-color: var(--border-strong);
  color: var(--text);
}

.chip--stop[data-reason="end_turn"] {
  border-color: var(--ok);
  background: var(--ok-subtle);
  color: var(--ok);
}

.chip--stop[data-reason="max_tokens"],
.chip--stop[data-reason="context_limit"],
.chip--stop[data-reason="max_iterations"],
.chip--stop[data-reason="loop_detected"],
.chip--stop[data-reason="tool_errors"],
.chip--stop[data-reason="budget"] {
  border-color: var(--warn);
  background: var(--warn-subtle);
  color: var(--warn);
}

.chip--stop[data-reason="refusal"] {
  border-color: var(--danger);
  background: var(--danger-subtle);
  color: var(--danger);
}

.chip--stop[data-reason="needs_input"] {
  border-color: var(--info);
  background: var(--info-subtle);
  color: var(--info);
}

/* the footer button that opens the permission popover */
.chip--why {
  cursor: pointer;
  border-style: dashed;
  color: var(--text-muted);
}

.chip--why:hover {
  border-style: solid;
  background: var(--surface-hover);
  color: var(--text);
}

.chip[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-subtle);
  color: var(--accent);
}

/* ══ banner ════════════════════════════════════════════════════════════════ */

.banner {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-inline-start-width: 3px;
  border-radius: var(--r-md);
  background: var(--bg-subtle);
  font-size: var(--fs-sm);
}

.banner__icon {
  flex: none;
  margin-block-start: 1px;
  color: var(--text-muted);
}

.banner__body {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

/* the title line is a bold run that OPENS the sentence (directly, or inside
   its one wrapper); a later bold run is emphasis and stays inline — "Try again
   in **19s**." broke onto its own line every second */
.banner__body > strong:first-child,
.banner__body > :is(span, p):first-child > strong:first-child {
  display: block;
  font-size: var(--fs-base);
  margin-block-end: var(--sp-1);
}

/* chips that sit side by side in running text (an error code, a request id)
   keep a space between them; a flex row already has its own gap */
.banner__body .chip + .chip {
  margin-inline-start: var(--sp-1);
}

.banner__body .row > .chip + .chip {
  margin-inline-start: 0;
}

.banner__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-block-start: var(--sp-2);
}

.banner__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 28px;
  block-size: 28px;
  flex: none;
  border-radius: var(--r-sm);
  color: var(--text-muted);
}

.banner__close:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.banner--info {
  border-color: var(--info);
  background: var(--info-subtle);
}

.banner--info .banner__icon {
  color: var(--info);
}

.banner--warn {
  border-color: var(--warn);
  background: var(--warn-subtle);
}

.banner--warn .banner__icon {
  color: var(--warn);
}

.banner--danger {
  border-color: var(--danger);
  background: var(--danger-subtle);
}

.banner--danger .banner__icon {
  color: var(--danger);
}

.banner--ok {
  border-color: var(--ok);
  background: var(--ok-subtle);
}

.banner--ok .banner__icon {
  color: var(--ok);
}

/* ══ rail ══════════════════════════════════════════════════════════════════ */

.rail {
  display: flex;
  flex-direction: column;
  block-size: 100%;
  min-block-size: 0;
  padding-block: var(--sp-3);
  gap: var(--sp-2);
}

.rail__ws {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: calc(100% - 2 * var(--sp-3));
  margin-inline: var(--sp-3);
  min-block-size: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  font-weight: var(--fw-medium);
  text-align: start;
}

.rail__ws:hover {
  background: var(--surface-hover);
  border-color: var(--border-strong);
}

/* the switcher and its `?` share one row inside the rail's padding (a
   full-width switcher pushed the `?` over the thread column) */
.rail__wsrow {
  gap: var(--sp-2);
  margin-inline: var(--sp-3);
  min-inline-size: 0;
}

.rail__wsrow .rail__ws {
  flex: 1 1 auto;
  inline-size: auto;
  margin-inline: 0;
  min-inline-size: 0;
}

.rail__ws .rail__name {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail__new {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: calc(100% - 2 * var(--sp-3));
  margin-inline: var(--sp-3);
  min-block-size: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--accent-fg);
  font-weight: var(--fw-medium);
}

.rail__new:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.rail__list {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  padding-inline: var(--sp-2);
  list-style: none;
}

.rail__group {
  margin-block-start: var(--sp-3);
  padding: 0 var(--sp-2) var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-faint);
}

.rail__item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: 100%;
  min-block-size: var(--tap);
  padding: var(--sp-2) var(--sp-2);
  border-radius: var(--r-md);
  color: var(--text-muted);
  text-align: start;
  text-decoration: none;
  font-size: var(--fs-sm);
}

.rail__item:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.rail__item[aria-current="page"] {
  background: var(--accent-subtle);
  color: var(--text);
  font-weight: var(--fw-medium);
}

.rail__title {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail__meta {
  flex: none;
  font-size: var(--fs-xs);
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.rail__item[data-pending] .rail__title {
  font-weight: var(--fw-semibold);
  color: var(--text);
}

.rail__item[data-pending] .dot {
  background: var(--warn);
}

/* one conversation: its link, and the `…` that opens Rename / Delete */
.rail__row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-inline-size: 0;
}

.rail__row > .rail__item {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.rail__more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  inline-size: var(--tap);
  block-size: var(--tap);
  border-radius: var(--r-md);
  color: var(--text-muted);
}

.rail__more:hover,
.rail__more[aria-expanded="true"] {
  background: var(--surface-hover);
  color: var(--text);
}

/* the title while it is being renamed: the row's own height, the rail's size */
.rail__rename {
  flex: 1 1 auto;
  min-inline-size: 0;
  min-block-size: var(--tap);
  font-size: var(--fs-sm);
}

/* the menu's destructive entry */
.rail__danger {
  color: var(--danger);
}

.rail__danger:hover {
  background: var(--danger-subtle);
  color: var(--danger);
}

.rail__item:disabled {
  background: none;
  color: var(--text-faint);
  cursor: not-allowed;
}

/* With a mouse and a rail column (≥720 px) the `…` takes the time's place on
   the hovered or focused row, so titles keep their width at rest; in the
   drawer and on touch screens it is always there, a 44 px target. */
@media (min-width: 720px) and (hover: hover) {
  .rail__more {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: var(--sp-1);
    inline-size: 32px;
    block-size: 32px;
    margin-block-start: -16px;
    opacity: 0;
    pointer-events: none;
  }

  .rail__row:hover .rail__more,
  .rail__row:focus-within .rail__more,
  .rail__more[aria-expanded="true"] {
    opacity: 1;
    pointer-events: auto;
    background: var(--surface-hover);
  }

  .rail__row:has(> .rail__item[aria-current="page"]) .rail__more {
    background: var(--accent-subtle);
  }

  .rail__row .rail__more:hover {
    background: var(--bg-inset);
    color: var(--text);
  }

  .rail__row:hover .rail__meta,
  .rail__row:focus-within .rail__meta,
  .rail__row:has(> .rail__more[aria-expanded="true"]) .rail__meta {
    visibility: hidden;
  }
}

.rail__foot {
  padding-inline: var(--sp-3);
  padding-block-start: var(--sp-2);
  border-block-start: 1px solid var(--border);
}

/* ══ meter ═════════════════════════════════════════════════════════════════ */

.meter {
  display: block;
  inline-size: 100%;
  block-size: 8px;
  border-radius: var(--r-full);
  background: var(--bg-inset);
  overflow: hidden;
}

.meter__bar {
  display: block;
  block-size: 100%;
  inline-size: calc(var(--pct) * 1%);
  max-inline-size: 100%;
  border-radius: var(--r-full);
  background: var(--ok);
  transition: inline-size var(--dur-slow) var(--ease-out);
}

.meter[data-level="near"] .meter__bar {
  background: var(--warn);
}

.meter[data-level="over"] .meter__bar {
  background: var(--danger);
}

.meter__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* ══ tabs ══════════════════════════════════════════════════════════════════ */

.tabs {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
}

.tabs__list {
  display: flex;
  /* never shrinks (overflow-x:auto made its min height 0, and a long Prompt
     panel squashed it); the panel below is what scrolls */
  flex: none;
  gap: var(--sp-1);
  padding-inline: var(--sp-2);
  border-block-end: 1px solid var(--border);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.tabs__tab {
  position: relative;
  min-block-size: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  border-block-end: 2px solid transparent;
  margin-block-end: -1px;
}

.tabs__tab:hover {
  color: var(--text);
}

.tabs__tab[aria-selected="true"] {
  color: var(--text);
  border-block-end-color: var(--accent);
}

.tabs__tab:disabled {
  color: var(--text-faint);
  cursor: not-allowed;
}

.tabs__panel {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  padding: var(--sp-4);
}

/* ══ table ═════════════════════════════════════════════════════════════════ */

.table {
  inline-size: 100%;
  font-size: var(--fs-sm);
  text-align: start;
}

.table caption {
  text-align: start;
  padding-block-end: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.table th,
.table td {
  padding: var(--sp-2) var(--sp-3);
  border-block-end: 1px solid var(--border);
  text-align: start;
  vertical-align: top;
}

.table thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  background: var(--bg-subtle);
  border-block-end: 1px solid var(--border-strong);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.table tbody tr:hover {
  background: var(--surface-hover);
}

.table tbody tr[aria-disabled="true"] td {
  color: var(--text-faint);
}

.table th[aria-sort] {
  cursor: pointer;
}

.table th[aria-sort]::after {
  content: " –";
  color: var(--text-faint);
}

.table th[aria-sort="ascending"]::after {
  content: " ↑";
  color: var(--text);
}

.table th[aria-sort="descending"]::after {
  content: " ↓";
  color: var(--text);
}

.table td.num {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

.table--keys td:nth-child(2),
.table--commands td:first-child,
.table--syncerrors td:first-child {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  overflow-wrap: anywhere;
}

.table--syncerrors td:last-child {
  color: var(--danger);
}

.table--usage td {
  font-variant-numeric: tabular-nums;
}

/* the per-row bar of the usage table; no chart library (§3.20) */
.table__bar {
  display: block;
  block-size: 6px;
  inline-size: calc(var(--pct) * 1%);
  min-inline-size: 2px;
  border-radius: var(--r-full);
  background: var(--accent);
}

.table__empty td {
  padding-block: var(--sp-6);
  text-align: center;
  color: var(--text-muted);
}

/* ══ tree ══════════════════════════════════════════════════════════════════ */

.tree {
  list-style: none;
  font-size: var(--fs-sm);
  min-inline-size: 0;
}

.tree__level {
  list-style: none;
  margin-block-start: var(--sp-3);
}

.tree__level > .tree__levelname {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-faint);
}

.tree__level ul {
  list-style: none;
  margin-inline-start: var(--sp-2);
  border-inline-start: 1px solid var(--border);
}

.tree__file {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-2);
  inline-size: 100%;
  /* a mouse needs no 44 px row: three names used to spread over 130 px */
  min-block-size: 32px;
  padding: var(--sp-1) var(--sp-2);
  border-inline-start: 2px solid transparent;
  margin-inline-start: -1px;
  text-align: start;
  color: var(--text-muted);
}

@media (pointer: coarse) {
  .tree__file {
    min-block-size: var(--tap);
  }
}

/* "Nothing here yet" (C-EMP-1) inside a level: in the file column, at the files' size */
.tree__empty {
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
}

.tree__file:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.tree__file[aria-current="true"] {
  border-inline-start-color: var(--accent);
  background: var(--accent-subtle);
  color: var(--text);
}

.tree__name {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  overflow-wrap: anywhere;
}

.tree__meta {
  font-size: var(--fs-xs);
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tree__file[data-readonly] .tree__name {
  color: var(--text-faint);
}

.tree__file[data-overridden] .tree__name {
  text-decoration: line-through;
  color: var(--text-faint);
}

.tree__file[data-error] {
  border-inline-start-color: var(--warn);
  background: var(--warn-subtle);
}

.tree__err {
  grid-column: 1 / -1;
  font-size: var(--fs-xs);
  color: var(--warn);
  overflow-wrap: anywhere;
}

/* ══ code block ════════════════════════════════════════════════════════════ */

.code {
  position: relative;
  margin-block: var(--sp-3);
  border: 1px solid var(--code-border);
  border-radius: var(--r-md);
  background: var(--code-bg);
  overflow: hidden;
}

.code__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-1) var(--sp-1) var(--sp-3);
  border-block-end: 1px solid var(--code-border);
}

.code__lang {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-faint);
}

.code__copy {
  min-block-size: 28px;
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.code__copy:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.code__copy[data-copied] {
  color: var(--ok);
}

.code pre {
  margin: 0;
  padding: var(--sp-3);
  overflow-x: auto;
  white-space: pre;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
}

/* a neutralised bidi / zero-width character, made visible (§4.7 rule 8) */
.inv {
  display: inline-block;
  padding-inline: 2px;
  border-radius: var(--r-sm);
  background: var(--warn-subtle);
  color: var(--warn);
  font-family: var(--font-mono);
  font-size: 0.85em;
  cursor: help;
}

/* ══ skeleton ══════════════════════════════════════════════════════════════ */

.skeleton {
  border-radius: var(--r-sm);
  background: var(--bg-inset);
  background-image: linear-gradient(
    90deg,
    var(--bg-inset) 0%,
    var(--surface-hover) 50%,
    var(--bg-inset) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
}

.skeleton--line {
  block-size: 1em;
  margin-block: var(--sp-1);
}

.skeleton--line:nth-child(3n) {
  inline-size: 72%;
}

.skeleton--line:nth-child(3n + 2) {
  inline-size: 88%;
}

.skeleton--block {
  block-size: 96px;
  border-radius: var(--r-md);
}

.skeleton--card {
  block-size: 132px;
  border-radius: var(--r-lg);
}

@media (prefers-reduced-motion: reduce) {
  .skeleton {
    background-image: none;
  }
}

/* ══ empty state ═══════════════════════════════════════════════════════════ */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-7) var(--sp-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
  text-align: center;
  color: var(--text-muted);
}

.empty__title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--text);
  margin: 0;
}

.empty__body {
  max-inline-size: 46ch;
  font-size: var(--fs-sm);
}

.empty--list {
  padding-block: var(--sp-6);
}

.empty--search {
  border-style: solid;
  border-color: var(--border);
  background: var(--bg-subtle);
  padding-block: var(--sp-5);
}

/* ══ keyboard hint ═════════════════════════════════════════════════════════ */

.kbd {
  display: inline-block;
  min-inline-size: 1.6em;
  padding: 1px var(--sp-1);
  border: 1px solid var(--border-strong);
  border-block-end-width: 2px;
  border-radius: var(--r-sm);
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: var(--lh-tight);
  text-align: center;
  white-space: nowrap;
}

/* ══ checklist (the /welcome setup rows and the Settings index) ════════════ */

.checklist {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.checklist__row {
  display: grid;
  grid-template-columns: 1.5em minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  inline-size: 100%;
  min-block-size: var(--tap);
  padding: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  text-align: start;
}

.checklist__mark {
  justify-self: center;
  color: var(--text-faint);
}

.checklist__label {
  font-weight: var(--fw-medium);
}

.checklist__meta {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  justify-self: end;
}

.checklist__row[data-status="done"] {
  background: var(--ok-subtle);
  border-color: var(--ok);
}

.checklist__row[data-status="done"] .checklist__mark {
  color: var(--ok);
}

.checklist__row[data-status="blocked"] {
  background: var(--warn-subtle);
  border-color: var(--warn);
}

.checklist__row[data-status="blocked"] .checklist__mark {
  color: var(--warn);
}

@media (max-width: 560px) {
  .checklist__row {
    grid-template-columns: 1.5em minmax(0, 1fr);
  }

  .checklist__meta,
  .checklist__row > .btn {
    grid-column: 2;
    justify-self: start;
  }
}

/* ══ touch: every interactive target reaches 44px on a coarse pointer ══════ */

@media (pointer: coarse) {
  .btn,
  .btn--icon {
    min-block-size: var(--tap);
  }

  .btn--icon {
    inline-size: var(--tap);
  }

  .field__input,
  .chips {
    min-block-size: var(--tap);
  }

  .field__reveal,
  .chips__remove,
  .toast__close,
  .banner__close,
  .coach__dismiss {
    inline-size: var(--tap);
    block-size: var(--tap);
  }

  .code__copy {
    min-block-size: var(--tap);
  }

  /* A chip that is a control (Copy, Raw, "Why was this refused?") is 22 px
     tall. Its hit area grows to 44 px without the pill growing, and stays
     clear of a neighbour 8 px away; unclipped, since a clipped pseudo-element
     takes no taps. */
  button.chip,
  a.chip {
    position: relative;
    /* above a positioned neighbour painted later (the turn footer is
       position: relative), which would otherwise take the bottom of the area */
    z-index: 1;
    overflow: visible;
  }

  button.chip::before,
  a.chip::before {
    content: "";
    position: absolute;
    inset: -12px -4px;
  }
}

/* ══ integration pass ══════════════════════════════════════════════════════
 *
 * Class names the view modules emit that no stylesheet had a rule for. Each
 * one was found by walking every class literal under app/ against every
 * selector in the five stylesheets, and each is here because a screenshot
 * showed the difference — an unstyled <dl> in the keyboard sheet, a code
 * block's language bar that lost its layout, a toast whose action button sat
 * on top of its own text.
 *
 * Where an element already has a styled twin (`.code__bar` / `.code__head`,
 * `.tool__fix` / `.tool__retry`) the rule is written once and shared, so the
 * two names cannot drift apart again.
 */

/* the keyboard sheet's definition list: key on the left, meaning on the right,
   baselines aligned, and one column when there is no room for two */
.keys {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-2) var(--sp-4);
  align-items: baseline;
  margin: 0;
}

.keys dt {
  margin: 0;
  white-space: nowrap;
}

.keys dd {
  margin: 0;
  color: var(--text-muted);
}

@media (max-width: 420px) {
  .keys {
    grid-template-columns: 1fr;
    gap: var(--sp-1) 0;
  }

  .keys dd {
    margin-block-end: var(--sp-2);
  }
}

/* lib/md.js emits `.code__bar`; views/chat/thread.js adds `code__head` to the
   same node when it decorates it with a Copy button. Both names get the bar. */
.code__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3);
  border-block-end: 1px solid var(--code-border);
  background: var(--bg-subtle);
  min-block-size: var(--sp-6);
}

/* an inline `code` span inside prose */
.code-inline {
  padding: 1px var(--sp-1);
  border-radius: var(--r-sm);
  background: var(--code-bg);
  font-family: var(--font-mono);
  font-size: 0.925em;
  overflow-wrap: anywhere;
}

/* a task-list item: the checkbox replaces the marker rather than joining it */
.task {
  list-style: none;
  margin-inline-start: calc(-1 * var(--sp-5));
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
}

.task > input[type="checkbox"] {
  margin-block-start: 0.25em;
  flex: none;
}

/* §4.7 invariant 7: a block past the 512 KiB ceiling is SHOWN, not parsed */
.prose__note {
  margin-block: var(--sp-2) var(--sp-1);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.prose__raw {
  max-block-size: 24em;
  margin-block: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--code-border);
  border-radius: var(--r-md);
  background: var(--code-bg);
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: var(--fs-sm);
}

/* the toast's own text node, beside its icon and its two buttons */
.toast__text {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.toast__action {
  flex: none;
  align-self: center;
}

/* a narrow reading column: the 404 screen, the boot error */
.page--narrow {
  max-inline-size: 46rem;
}

/* the header's per-route slot (the conversation title) and the offline chip */
.app__headerslot {
  flex: 1 1 auto;
  min-inline-size: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  overflow: hidden;
}

.app__offline {
  flex: none;
  white-space: nowrap;
}

.app__offline-short {
  display: none;
}

/* below 720 px the sentence is wider than the slot beside the brand */
@media (max-width: 720px) {
  .app__offline-long {
    display: none;
  }

  .app__offline-short {
    display: inline;
  }
}

.brand__name {
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

/* the two popover variants: the `?` teaching popover and the permission
   provenance popover, which is wider because it shows four layers */
.pop--help {
  inline-size: min(340px, calc(100vw - 2 * var(--sp-4)));
}

.pop--why {
  inline-size: min(460px, calc(100vw - 2 * var(--sp-4)));
}

/* the in-context fixes on a refused tool card, and the jump-to-question link */
.tool__fix,
.tool__retry,
.ask__jump,
.ask__dismiss {
  flex: none;
  align-self: flex-start;
}

/* a question card is not an approval card: no danger accent, no typed binding */
.ask--question {
  border-inline-start-color: var(--accent);
}

/* the queued send's own text, which must not push its Cancel button off */
.composer__queuedtext {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* the conversation title in the header slot: a block (a .chip is inline-flex,
   where text-overflow does nothing) that may shrink but never grow */
.chat__title {
  display: inline-block;
  flex: 0 1 auto;
  max-inline-size: 100%;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* "N setup steps left · Finish": the pill is the affordance, so its label is
   not underlined inside it until it is pointed at */
.chat__setup {
  text-decoration: none;
}

.chat__setup:hover {
  text-decoration: underline;
}

/* the overlay host: a positioning context only, never a painted box */
.overlays {
  position: static;
}
