/* ui-align-1 (owner 30-09, docs/PLAN-2026-09-30-ui-align-1.md): one gutter, one row height, one activity line.
   The avatar is 28px with a 12px gap (style.css), so every assistant element starts at the answer text's left edge.
   A "row" is 28px tall so its centre meets the avatar's centre; the 44px touch target is an invisible hit area, not
   layout height (reasoning.css's 44px min-height put the reasoning line 8px below the avatar). Loaded after style.css
   and reasoning.css (style.css is not in the overlay). Theme tokens only, so light and dark follow. */
:root { --msg-row: 28px; }

/* ── The user's prompt: a block bubble (no inline-block line strut) with the avatar centred on its FIRST line
   (10px padding + half of one 0.95rem x 1.55 line), so it holds for multi-line prompts too. */
.msg.user { align-items: flex-start; margin-bottom: 8px; }
.msg.user .msg-body { display: flex; flex-direction: column; align-items: flex-end; text-align: left; }
.msg.user .msg-content { display: block; max-width: 100%; }
.msg.user .msg-avatar { margin-top: calc(10px + 0.95rem * 0.775 - 14px); }
/* a prompt that starts with its attachment chips: the avatar sits on the chip row */
.msg.user:has(> .msg-body > .msg-media:first-child) .msg-avatar { margin-top: 1px; }

/* Copy the prompt: under the bubble; shown on hover and keyboard focus (opacity only, so Tab still reaches it),
   always shown on touch screens. */
.msg-user-actions { display: flex; justify-content: flex-end; gap: 2px; margin-top: 2px; opacity: 0; pointer-events: none; transition: opacity 0.15s; }
.msg.user:hover .msg-user-actions,
.msg.user:focus-within .msg-user-actions { opacity: 1; pointer-events: auto; }
@media (hover: none) { .msg-user-actions { opacity: 1; pointer-events: auto; } }
.msg-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 32px; min-width: 32px; padding: 0 8px;
  border: 0; border-radius: 8px; background: transparent; color: var(--text-muted);
  font: inherit; font-size: 0.78rem; cursor: pointer; transition: background 0.12s, color 0.12s;
}
.msg-icon-btn:hover { background: var(--bg-hover); color: var(--text); }
.msg-icon-btn:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.msg-icon-btn svg { width: 16px; height: 16px; flex: none; }
.msg-icon-btn .copy-done { display: none; }
.msg-icon-btn.is-copied .copy-idle { display: none; }
.msg-icon-btn.is-copied .copy-done { display: inline; color: var(--success); }
.msg-icon-btn .copy-word:empty { display: none; }
.ui-sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── The answer: the working status sits on the avatar's row */
.msg.assistant .msg-status { min-height: var(--msg-row); padding-top: 4px; }
.msg.assistant .msg-status-spinner { margin-top: 4px; }
/* style.css hides the answer body while the turn works and no reply streamed; the activity line IS the status
   while steps run and sites are searched, so the body (the line) shows then. */
.msg.assistant.is-working.has-activity .msg-body { display: block; }

/* ── The activity line: [icon] Thought for 6s · searched 3 sites [· 1 failed] › */
.turn-activity { margin: 0 0 10px; font-size: 0.82rem; color: var(--text-muted); }
.turn-activity[hidden] { display: none; }
.ta-toggle {
  position: relative; display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; min-height: var(--msg-row); padding: 0 4px 0 0;
  border: 0; border-radius: 6px; background: transparent; color: inherit;
  font: inherit; font-weight: 500; text-align: left; cursor: pointer; transition: color 0.15s;
}
.ta-toggle::after { content: ""; position: absolute; inset: -8px -4px; }   /* 44px touch target; the row stays 28px */
.ta-toggle:hover { color: var(--text); }
.ta-toggle:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.ta-icon { display: inline-flex; width: 16px; height: 16px; flex: none; color: var(--link); border-radius: 50%; }
.ta-icon svg { display: block; width: 16px; height: 16px; }
.ta-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ta-time { font-variant-numeric: tabular-nums; }
.ta-fail { flex: none; color: var(--warn-fg); white-space: nowrap; }
.ta-fail:empty { display: none; }
.ta-chevron::before { content: "›"; display: inline-block; font-size: 1.15rem; line-height: 1; transition: transform 0.15s; }
.ta-toggle[aria-expanded="true"] .ta-chevron::before { transform: rotate(90deg); }

/* live: the icon breathes and the words shimmer (reasoning-ui-1's pulsing brain, on the text-sized icon) */
.turn-activity.is-live .ta-icon { animation: ta-pulse 1.6s ease-in-out infinite; }
.turn-activity.is-live .ta-text {
  background: linear-gradient(90deg, var(--text-muted) 0%, var(--text) 50%, var(--text-muted) 100%);
  background-size: 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: ta-shimmer 2.2s linear infinite;
}
@keyframes ta-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.55; transform: scale(1.12); } }
@keyframes ta-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }

/* the thread under the icon: the live per-site rows and the opened panel hang from the icon's centre line */
.ta-live, .ta-panel {
  margin: 4px 0 2px 7px; padding: 0 0 0 13px; border-left: 2px solid var(--border); overflow-wrap: anywhere;
}
.ta-live[hidden], .ta-panel[hidden], .ta-steps[hidden], .ta-thought[hidden], .ta-h[hidden] { display: none; }
.ta-panel { max-height: min(50vh, 420px); overflow-y: auto; padding-block: 2px; }
.ta-h { margin: 2px 0 4px; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.03em; }
.ta-steps:not([hidden]) + .ta-thought .ta-h { margin-top: 10px; }
.turn-activity .ta-step { padding: 2px 0; line-height: 1.5; }
.turn-activity .step-fail { color: var(--text); }
.ta-reasoning { font-size: 0.84rem; line-height: 1.55; white-space: pre-wrap; }

@media (prefers-reduced-motion: reduce) {
  .turn-activity.is-live .ta-icon, .turn-activity.is-live .ta-text { animation: none; }
  .turn-activity.is-live .ta-text { background: none; color: inherit; }
  .ta-chevron::before, .ta-toggle, .msg-user-actions { transition: none; }
}

/* search-down-1: the Search button while the search service is down (never colour alone: the warning icon, tooltip
   and accessible name change too). Theme tokens only (ui-align-1). Dark: --danger-text on a --danger-border fill reads
   red (6.9:1 in style.css's dark values; the light text border keeps 3:1 against the page); light: --danger-text on
   --danger-bg (5.9:1). */
.composer-web-search-btn.search-down,
.composer-web-search-btn.search-down[aria-pressed="true"],
.composer-web-search-btn.search-down:hover { color: var(--danger-text); border-color: var(--danger-text); background: var(--danger-border); }
[data-theme="light"] .composer-web-search-btn.search-down,
[data-theme="light"] .composer-web-search-btn.search-down[aria-pressed="true"],
[data-theme="light"] .composer-web-search-btn.search-down:hover { background: var(--danger-bg); }
.composer-web-search-btn .composer-web-search-down-icon { flex: none; margin-left: 2px; }

/* chat-ui-1 (owner 11-10, docs/PLAN-2026-10-11-chat-ui-1.md). Theme tokens only (ui-align-1).
   The jump button: one round button centred on the upper edge of the message box area, so it follows that area's
   height by itself (attachment chips, a tall draft, the workspace pickers). app.js updateChatJump() shows it, hides
   it and turns it: down arrow = go to the latest message, up arrow (.is-up) = go to the top. A chat with messages
   keeps 56px free under its last line, so the button never covers text. */
.composer-wrap { position: relative; }
.chat:has(> .msg) { padding-bottom: 56px; }
.chat-jump-btn {
  position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%); z-index: 30;
  display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0;
  border: 1px solid var(--border-strong); border-radius: 50%; background: var(--bg-elevated); color: var(--text);
  cursor: pointer; box-shadow: 0 2px 10px var(--shadow-drawer); transition: background 0.12s;
}
.chat-jump-btn::before { content: ""; position: absolute; inset: -4px; }   /* 44px touch target; the button stays 36px */
.chat-jump-btn:hover { background: var(--bg-hover); }
.chat-jump-btn:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.chat-jump-btn svg { display: block; transition: transform 0.18s ease; }
.chat-jump-btn.is-up svg { transform: rotate(180deg); }
/* something new arrived below a reader who scrolled up */
.chat-jump-btn.has-new::after {
  content: ""; position: absolute; top: -3px; right: -3px; width: 8px; height: 8px;
  border: 2px solid var(--bg); border-radius: 50%; background: var(--link);
}
@media (prefers-reduced-motion: reduce) {
  .chat { scroll-behavior: auto; }
  .chat-jump-btn, .chat-jump-btn svg { transition: none; }
}

/* The Search switch: the globe alone in a round button. On = the theme's blue (--link), off = the muted icon colour
   of the other composer icons. The search-down rules above have one class more and still win; a switch the
   administrator turned off is dimmed by app.js as before. */
.composer-web-search-btn { justify-content: center; gap: 4px; min-width: 32px; height: 32px; padding: 0 7px; }
.composer-web-search-btn[aria-pressed="true"] { color: var(--link); border-color: var(--link); background: var(--accent-blue-soft); }

/* sidebar-collapse-2 (owner 13-10): the sidebar's collapse / expand control on wide screens, in one place at the pane's
   top-left: open = the full pane, chevron pointing left; collapsed = a slim rail on the far left, chevron pointing right.
   Up to 860px the pane is the drawer with its menu button, as before. */
.sidebar-toggle { display: none; }
@media (min-width: 861px) {
  .sidebar { position: relative; transition: width 0.2s ease; }
  .sidebar .sidebar-head { padding-left: 52px; gap: 6px; }
  .sidebar .sidebar-head .sidebar-actions { gap: 2px; }
  .sidebar-toggle {
    display: grid; place-items: center; position: absolute; top: 13px; left: 12px; z-index: 2;
    width: 30px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 9px;
    background: var(--bg); color: var(--text-muted); cursor: pointer; box-shadow: 0 1px 2px var(--shadow-drawer);
    transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
  }
  .sidebar-toggle:hover { color: var(--text); background: var(--bg-hover); border-color: var(--text-muted); }
  .sidebar-toggle:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
  .sidebar-toggle svg { transition: transform 0.2s ease; }
  .shell.sidebar-collapsed .sidebar { width: 54px; }
  .shell.sidebar-collapsed .sidebar > :not(.sidebar-toggle) { display: none; }
  .shell.sidebar-collapsed .sidebar-toggle svg { transform: rotate(180deg); }
}
@media (prefers-reduced-motion: reduce) { .sidebar, .sidebar-toggle, .sidebar-toggle svg { transition: none; } }

/* ── paste-card-1 (14-10): a large paste is a card above the message box, a long sent prompt one card in its bubble; click: the full
   text in the app modal's look. Theme tokens only, so light and dark follow; no motion with reduced motion. */
.paste-cards { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0 10px; }
.paste-card { position: relative; display: flex; width: 280px; max-width: 100%; min-width: 0; animation: paste-card-in 0.18s ease-out; }
.paste-card-open {
  display: flex; align-items: center; gap: 12px; width: 100%; min-width: 0; min-height: 64px; padding: 10px 30px 10px 10px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--bg); color: var(--text);
  box-shadow: 0 1px 2px var(--shadow-drawer); font: inherit; text-align: left; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.paste-card-open:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.paste-card-open:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.paste-card-icon {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px;
  color: var(--badge-blue); background: var(--badge-blue-bg);
}
.paste-kind-code .paste-card-icon, .paste-preview.paste-kind-code .paste-card-icon { color: var(--text); background: var(--bg-hover); }
.paste-kind-json .paste-card-icon, .paste-preview.paste-kind-json .paste-card-icon { color: var(--warn-fg); background: var(--cache-bg); background: color-mix(in srgb, var(--warn-fg) 13%, transparent); }
.paste-kind-table .paste-card-icon, .paste-preview.paste-kind-table .paste-card-icon { color: var(--badge-green); background: var(--badge-green-bg); }
.paste-card-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.paste-card-title { overflow: hidden; font-size: 0.86rem; font-weight: 600; line-height: 1.3; white-space: nowrap; text-overflow: ellipsis; }
.paste-card-meta { overflow: hidden; color: var(--text-muted); font-size: 0.76rem; line-height: 1.3; white-space: nowrap; text-overflow: ellipsis; }
.paste-card.is-adding .paste-card-icon svg { animation: paste-card-pulse 0.9s ease-in-out infinite; }
.paste-card.is-over .paste-card-open { border-color: var(--warn-fg); }
.paste-card.is-over .paste-card-meta { color: var(--warn-fg); font-weight: 600; }
.paste-card-remove {
  position: absolute; top: -7px; right: -7px; display: grid; place-items: center; width: 22px; height: 22px; padding: 0;
  border: 2px solid var(--bg); border-radius: 50%; background: var(--text); color: var(--bg); cursor: pointer;
  transition: transform 0.12s, background 0.12s;
}
.paste-card-remove::after { content: ""; position: absolute; inset: -10px; }   /* a 42px touch target on a 22px button */
.paste-card-remove:hover { transform: scale(1.08); }
.paste-card-remove:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
/* in the sent prompt: the card sits on the chip row, right-aligned like the bubble */
.msg.user .msg-media .paste-card { animation: none; }
.msg.user .msg-media .paste-card-open { padding-right: 14px; background: var(--user-bubble); border-color: transparent; box-shadow: none; }
.msg.user .msg-media .paste-card-open:hover { border-color: var(--border-strong); }

/* the preview */
.paste-preview-overlay { z-index: 320; }
.paste-preview { display: flex; flex-direction: column; width: min(760px, 100%); max-height: min(85vh, 820px); overflow: hidden; padding: clamp(14px, 4vw, 20px) clamp(14px, 4vw, 20px) 16px; }
.paste-preview-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.paste-preview-heading { flex: 1; min-width: 0; }
.paste-preview-heading h3 { margin: 0; overflow: hidden; font-size: 1rem; white-space: nowrap; text-overflow: ellipsis; }
.paste-preview-meta { margin: 2px 0 0; color: var(--text-muted); font-size: 0.78rem; }
.paste-preview-close {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-muted); cursor: pointer;
}
.paste-preview-close:hover { background: var(--bg-hover); color: var(--text); }
.paste-preview-close:focus-visible, .paste-preview-text:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.paste-preview-close svg { width: 14px; height: 14px; }
.paste-preview-text {
  flex: 1 1 auto; min-height: 120px; margin: 0; padding: 12px 14px; overflow: auto; border: 1px solid var(--border);
  border-radius: 10px; background: var(--bg); color: var(--text); font: inherit; font-size: 0.86rem; line-height: 1.6;
  white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 4;
}
.paste-preview-text.is-mono { font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace; font-size: 0.8rem; line-height: 1.55; }
.paste-preview-warn { margin: 10px 0 0; color: var(--warn-fg); font-size: 0.8rem; font-weight: 600; }
.paste-preview .app-modal-actions { margin-top: 14px; }

@keyframes paste-card-in { from { opacity: 0; transform: translateY(4px) scale(0.98); } }
@keyframes paste-card-pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  .paste-card, .paste-card.is-adding .paste-card-icon svg { animation: none; }
  .paste-card-open, .paste-card-remove { transition: none; }
}
