/* ============================================================
   Chat kit polish — styles every class emitted by Chat /
   ChatMessage / ChatComposer / AICat. Before this block the
   chat-* classes had no CSS and rendered as unstyled paragraphs.
   ============================================================ */
.chat {
  display: flex; flex-direction: column;
  flex: 1; min-height: 0; gap: var(--space-3);
}
.chat-head {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: var(--space-3) 0 var(--space-2);
  font-family: var(--ff-mono); font-size: var(--fs-xs);
  color: var(--fg-3); text-transform: lowercase; letter-spacing: 0.02em;
  border-bottom: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
  margin-bottom: var(--space-2);
}
.chat-head .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.chat-head .ds-chat-title,
.chat-head > span:nth-child(2) {
  font-family: var(--ff-body); font-size: var(--fs-h4);
  font-weight: 600; color: var(--fg);
  text-transform: none; letter-spacing: var(--tr-tight, -0.01em); line-height: 1.2;
}
.chat-head .sub { color: var(--fg-3); }
.chat-head .spread { flex: 1; }

.chat-thread {
  display: flex; flex-direction: column; gap: var(--space-3);
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--space-2) 0;
  scrollbar-width: thin; scrollbar-color: var(--bg-3) transparent;
}
@media (prefers-reduced-motion: no-preference) {
  .chat-thread { scroll-behavior: smooth; }
}
.chat-thread::-webkit-scrollbar { width: 8px; }
.chat-thread::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: var(--r-0); }
.chat-empty {
  margin: auto;
  text-align: center;
  color: var(--fg-3);
  font-family: var(--ff-mono);
  pointer-events: none;
}
.chat-empty-title { font-size: var(--fs-sm); margin: 0 0 var(--space-1); }
.chat-empty-sub { font-size: var(--fs-tiny); margin: 0; opacity: .7; }

.chat-msg { display: flex; gap: var(--space-2-75); align-items: flex-start; padding: var(--space-1-75) 0; position: relative; min-width: 0; }
.chat-msg.you { flex-direction: row-reverse; }
.chat-msg.you .chat-stack { align-items: flex-end; }
.chat-msg:hover { background: color-mix(in oklab, var(--fg) 4%, transparent); padding: var(--space-1-75) 0; margin: 0; border-radius: var(--r-0); transition: background var(--dur-base) var(--ease); }

.chat-avatar {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 50%; background: var(--bg-3); color: var(--fg);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--ff-mono); font-size: var(--fs-micro); font-weight: 600;
  text-transform: lowercase; letter-spacing: 0.02em; user-select: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  position: relative;
}
.chat-msg:hover .chat-avatar { transform: scale(1.03); box-shadow: 0 1px 4px color-mix(in oklab, var(--fg) 6%, transparent); }
.chat-msg.you .chat-avatar {
  background: color-mix(in oklab, var(--accent) 18%, var(--bg-3));
  color: var(--accent-ink);
}
.chat-msg.aicat .chat-avatar {
  background: color-mix(in oklab, var(--mascot) 26%, var(--bg-2));
  color: var(--mascot-deep);
}

.chat-stack {
  display: flex; flex-direction: column; gap: var(--space-1);
  max-width: min(70%, 56ch); min-width: 0;
  flex: 0 1 auto; overflow: hidden;
}

.chat-bubble {
  /* 14px inline has no tier (--space-2-75 is 12, --space-3 is 16). It is the
     shared bubble/attachment inset used by .chat-file/.chat-pdf-head below;
     snapping only this one would visibly desync the bubble from its cards. */
  padding: var(--space-2-5) 14px; background: var(--bg-2); color: var(--fg);
  max-width: 100%;
  border-radius: var(--r-2); line-height: 1.55;
  word-wrap: break-word; overflow-wrap: anywhere;
  font-size: var(--fs-sm);
  min-width: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.chat-msg:hover .chat-bubble { transform: translateY(-1px); box-shadow: 0 2px 8px color-mix(in oklab, var(--fg) 6%, transparent); transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease); }
/* Own bubble — calm tinted lead, not a full electric fill (chat stays readable). */
.chat-msg.you .chat-bubble { background: var(--accent-tint); color: var(--fg); }
.chat-msg.aicat .chat-bubble {
  background: color-mix(in oklab, var(--mascot) 14%, var(--bg-2));
  border: 1px solid color-mix(in oklab, var(--mascot) 28%, transparent);
}
.chat-bubble code {
  /* em-relative on purpose: inline code tracks the size of the prose it sits
     inside (the mono face runs optically large next to the system stack, hence
     0.92). An absolute --fs-* tier would decouple it from its own paragraph. */
  font-family: var(--ff-mono); font-size: 0.92em;
  background: color-mix(in oklab, var(--fg) 10%, transparent);
  /* 1px block is deliberately under --space-hair (2px): inline <code> must not
     grow the line box of the prose it sits inside. */
  padding: 1px var(--space-1-75); border-radius: var(--r-0);
}
.chat-msg.you .chat-bubble code { background: color-mix(in oklab, var(--fg) 10%, transparent); }
.chat-bubble a {
  color: inherit; text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in oklab, currentColor 50%, transparent);
}
.chat-bubble a:hover { text-decoration-color: currentColor; }
.chat-bubble strong { font-weight: 700; }
.chat-bubble em { font-style: italic; }

.chat-bubble.chat-md { line-height: 1.6; }
.chat-bubble.chat-md > :first-child { margin-top: 0; }
.chat-bubble.chat-md > :last-child { margin-bottom: 0; }
.chat-bubble.chat-md h1,
.chat-bubble.chat-md h2,
.chat-bubble.chat-md h3,
.chat-bubble.chat-md h4 {
  font-family: var(--ff-body); font-weight: 600;
  margin: var(--space-2) 0 var(--space-1); line-height: var(--lh-snug);
}
/* em-relative on purpose, NOT --fs-h1..h3: markdown headings inside a chat
   bubble are a hierarchy WITHIN the bubble's own type size, not page headings.
   The --fs-h* tiers are fluid clamp()s tuned to page container queries and
   would render a bubble heading at 34px+, dwarfing the message it labels.
   These stay a tight ratio ladder off whatever size the bubble is set at. */
.chat-bubble.chat-md h1 { font-size: 1.15em; }
.chat-bubble.chat-md h2 { font-size: 1.08em; }
.chat-bubble.chat-md h3 { font-size: 1.04em; }
.chat-bubble.chat-md p { margin: var(--space-2) 0; }
.chat-bubble.chat-md ul,
/* 22px is the list-marker hang, matched to the mono digit+period width so
   ordered markers align with the bubble text edge - not a spacing-scale value. */
.chat-bubble.chat-md ol { margin: var(--space-2) 0; padding-left: 22px; }
.chat-bubble.chat-md li { margin: var(--space-1) 0; }
.chat-bubble.chat-md blockquote {
  margin: var(--space-2) 0; padding: var(--space-1) var(--space-2-75);
  /* DELIBERATE, but slimmed to the --bw-rule tier. This is a real markdown
     <blockquote> inside a chat bubble: the left rule is the standard
     typographic quotation mark, not a colored alert stripe (the tone is a
     currentColor mix that inherits the bubble's own ink — never an accent).
     A 3px off-scale literal read as the generic tell; 2px reads as type. */
  border-left: var(--bw-rule) solid color-mix(in oklab, currentColor 30%, transparent);
  color: color-mix(in oklab, currentColor 75%, transparent); font-style: italic;
}
.chat-bubble.chat-md pre {
  background: var(--bg);
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
  padding: var(--space-2-75) var(--space-3); border-radius: var(--r-1); overflow-x: auto;
  font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.55;
  color: var(--fg); margin: var(--space-2) 0;
}
/* When injectCodeCopy has wrapped the fence (.chat-code-block), reserve room
   for the absolute .chat-code-lang tab. This selector outranks the bare
   .chat-code-block pre reservation in chat.css, which the 2-class md pre
   selector above would otherwise override. */
.chat-code-block .chat-bubble.chat-md pre,
.chat-bubble.chat-md .chat-code-block pre {
  padding-top: calc(var(--space-3) + 4px);
}
/* Markdown tables + horizontal rules: agents routinely emit them, but they were
   unstyled (bare unspaced cells, vanished rules). */
.chat-bubble.chat-md table { border-collapse: collapse; width: auto; max-width: 100%; margin: var(--space-2) 0; font-size: .95em; /* em-relative: a table inside a bubble reads one notch down from the bubble's own copy, not off an absolute tier */ display: block; overflow-x: auto; }
.chat-bubble.chat-md th,
.chat-bubble.chat-md td { border: var(--bw-hair) solid var(--rule); padding: var(--space-1) var(--space-2-5); text-align: left; }
.chat-bubble.chat-md th { background: color-mix(in oklab, var(--fg) 5%, transparent); font-weight: 600; }
.chat-bubble.chat-md hr { border: 0; border-top: var(--bw-hair) solid var(--rule); margin: var(--space-2-75) 0; }

/* Mermaid diagram blocks — rendered SVG swapped in over the fenced source by
   src/mermaid.js's renderMermaidBlocksUnder(); the source .pre stays in the
   DOM (display:none) behind a source/diagram toggle button. */
.ds-mermaid-block {
  position: relative; margin: var(--space-2) 0;
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
  border-radius: var(--r-1); background: var(--bg); padding: var(--space-2-75) var(--space-3);
}
.ds-mermaid-diagram { overflow-x: auto; display: flex; justify-content: center; }
.ds-mermaid-diagram svg { max-width: 100%; height: auto; }
.ds-mermaid-toggle {
  position: absolute; top: 6px; right: 6px;
  font: inherit; font-size: var(--fs-xs); line-height: 1;
  background: color-mix(in oklab, var(--fg) 8%, transparent);
  color: var(--fg); border: none; border-radius: var(--r-1);
  padding: var(--space-1) var(--space-2); cursor: pointer;
}
.ds-mermaid-toggle:hover { background: color-mix(in oklab, var(--fg) 14%, transparent); }

/* Inline/display math — KaTeX HTML swapped into text nodes by
   src/math.js's renderMathBlocksUnder(). Display math centers on its own line;
   inline math sits within running text. */
.ds-math-display { display: block; margin: var(--space-2) 0; text-align: center; overflow-x: auto; }
.ds-math-inline { display: inline-block; }

.chat-msg .chat-bubble.chat-code,
.chat-msg.you .chat-bubble.chat-code,
.chat-bubble.chat-code {
  padding: 0; background: var(--bg);
  color: var(--fg);
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
  overflow: hidden; max-width: 100%; min-width: 0;
}
.chat-bubble.chat-code pre,
.chat-bubble pre,
.chat-msg pre {
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--bg-3) transparent;
}
.chat-bubble pre code,
.chat-msg pre code {
  display: block;
  white-space: pre;
  min-width: 0;
}
.chat-code-head {
  display: flex; align-items: center; gap: var(--space-2-5);
  padding: var(--space-2) var(--space-2-75);
  background: color-mix(in oklab, var(--fg) 6%, var(--bg-2));
  border-bottom: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
  font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3);
}
.chat-code-head .lang { text-transform: uppercase; font-weight: 700; color: var(--accent-ink); letter-spacing: 0.06em; }
.chat-code-head .filename,
.chat-code-head .name { color: var(--fg-2); font-weight: 500; }
.chat-code-head .spread { flex: 1; }
.chat-bubble.chat-code pre {
  margin: 0; padding: var(--space-2-75) var(--space-3); background: transparent;
  font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.55;
  overflow-x: auto; color: var(--fg); border-radius: 0;
}
.chat-bubble.chat-code code { background: transparent; padding: 0; font-size: inherit; }
.chat-bubble.chat-code .token.keyword,
.chat-bubble.chat-code .token.atrule,
.chat-bubble.chat-code .token.selector { color: var(--accent-ink); }
.chat-bubble.chat-code .token.string,
.chat-bubble.chat-code .token.attr-value { color: var(--code-str-alt, var(--mascot)); }
.chat-bubble.chat-code .token.comment { color: var(--fg-3); font-style: italic; }
.chat-bubble.chat-code .token.number,
.chat-bubble.chat-code .token.boolean { color: var(--code-num, var(--sun)); }
.chat-bubble.chat-code .token.punctuation { color: var(--fg-2); }
.chat-bubble.chat-code .token.property,
.chat-bubble.chat-code .token.attr-name { color: var(--code-keyword, var(--sky)); }

.chat-msg.you .chat-image,
.chat-msg .chat-image,
.chat-image {
  display: inline-block; border-radius: var(--r-1); overflow: hidden;
  max-width: min(100%, 480px); background: var(--bg-2);
  text-decoration: none; color: var(--fg);
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.chat-msg:hover .chat-image,
.chat-image:hover {
  border-color: var(--rule);
}
.chat-image img { display: block; width: 100%; height: auto; max-height: 360px; object-fit: cover; }
.chat-image .cap,
.chat-image .caption { display: block; padding: var(--space-2) var(--space-2-75); font-size: var(--fs-xs); color: var(--fg-3); font-family: var(--ff-mono); }

.chat-msg.you .chat-file,
.chat-msg .chat-file,
.chat-file {
  display: flex; align-items: center; gap: var(--space-2-75); padding: var(--space-2-75) 14px;
  background: var(--bg-2); border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
  border-radius: var(--r-1); text-decoration: none; color: var(--fg);
  max-width: min(100%, 360px);
  transition: background var(--dur-snap, .15s) var(--ease, ease), border-color var(--dur-snap, .15s) var(--ease, ease);
}
.chat-file:hover { background: var(--bg-3); }
.chat-file .glyph {
  /* 22px is the ICON size inside a 36px chip — matched to the chip box, not to
     the type scale (--fs-xl is 21px, and above it every rung is a fluid
     heading clamp). Snapping it visibly resizes the mark. */
  font-size: 22px; width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-3);
  color: var(--fg-2); border-radius: var(--r-0); flex-shrink: 0; font-family: var(--ff-mono);
}
.chat-file > div { display: flex; flex-direction: column; gap: var(--space-hair); min-width: 0; }
.chat-file .name {
  font-weight: 600; font-size: var(--fs-sm);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.chat-file .meta { display: flex; flex-direction: column; gap: var(--space-hair); min-width: 0; flex: 1; }
.chat-file .size { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
.chat-file .go { font-family: var(--ff-mono); font-size: var(--fs-body); color: var(--fg-3); flex-shrink: 0; }
.chat-file:hover .go { color: var(--accent-ink); }

.chat-msg.you .chat-pdf,
.chat-msg .chat-pdf,
.chat-pdf {
  background: var(--bg-2);
  color: var(--fg);
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
  border-radius: var(--r-1); overflow: hidden; max-width: min(100%, 480px);
  transition: box-shadow 0.12s ease, border-color 0.12s ease;
}
.chat-msg:hover .chat-pdf { border-color: var(--rule); }
.chat-pdf-head {
  display: flex; align-items: center; gap: var(--space-2-5); padding: var(--space-2-5) 14px;
  background: color-mix(in oklab, var(--fg) 5%, var(--bg-2));
  border-bottom: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
}
.chat-pdf-head .glyph { font-size: var(--fs-lg); color: var(--mascot); flex-shrink: 0; }
.chat-pdf-head .name { flex: 1; font-weight: 600; font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-pdf-head .size { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
.chat-pdf-head a { color: var(--accent-ink); font-family: var(--ff-mono); font-size: var(--fs-xs); text-decoration: none; }
.chat-pdf embed,
.chat-pdf iframe,
.chat-pdf object { width: 100%; height: 360px; border: 0; display: block; }

.chat-msg.you .chat-link,
.chat-msg .chat-link,
.chat-link {
  display: grid; grid-template-columns: 80px 1fr; gap: var(--space-2-75); padding: var(--space-2-5);
  background: var(--bg-2);
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
  border-radius: var(--r-1); text-decoration: none; color: var(--fg);
  max-width: min(100%, 480px);
  transition: background var(--dur-snap, .15s) var(--ease, ease), border-color var(--dur-snap, .15s) var(--ease, ease), box-shadow 0.15s ease;
}
.chat-msg:hover .chat-link,
.chat-link:hover {
  background: var(--bg-3);
}
.chat-link:not(:has(.thumb)):not(:has(img)) { grid-template-columns: 1fr; }
.chat-link .thumb,
.chat-link img.thumb { width: 80px; height: 80px; border-radius: var(--r-0); object-fit: cover; background: var(--bg-3) center/cover no-repeat; }
.chat-link .meta { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.chat-link .host { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-transform: lowercase; }
.chat-link .title { font-weight: 600; font-size: var(--fs-sm); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.chat-link .desc { font-size: var(--fs-xs); color: var(--fg-2); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.chat-meta {
  display: flex; align-items: center; gap: var(--space-1-75);
  font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3);
  padding: 0 var(--space-1-75); letter-spacing: 0.02em;
}
.chat-meta .who { font-weight: 600; color: var(--fg-2); }
.chat-meta .who::after { content: ' ·'; color: var(--fg-3); font-weight: 400; }
.chat-meta .t { color: var(--fg-3); }
.chat-meta .tick { color: var(--fg-3); margin-left: var(--space-hair); letter-spacing: -2px; font-family: var(--ff-mono); }
.chat-meta .tick.read { color: var(--accent-ink); }

.chat-reactions {
  display: flex; gap: var(--space-1); flex-wrap: wrap; margin-top: var(--space-hair);
}
.chat-reactions .rxn {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-hair) var(--space-2); background: var(--bg-2);
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
  border-radius: var(--r-pill); font-size: var(--fs-xs);
  cursor: pointer; user-select: none;
  transition: background var(--dur-snap, .12s) var(--ease, ease), border-color var(--dur-snap, .12s) var(--ease, ease), transform 0.12s ease;
  position: relative;
}
.chat-reactions .rxn:hover { background: var(--bg-3); transform: scale(1.06); }
.chat-reactions .rxn.you {
  background: color-mix(in oklab, var(--accent) 18%, var(--bg-2));
  border-color: color-mix(in oklab, var(--accent) 55%, transparent);
  color: var(--accent-ink);
}
.chat-reactions .rxn .e { font-size: var(--fs-xs); line-height: 1; }
.chat-reactions .rxn .n { font-family: var(--ff-mono); font-weight: 600; font-size: var(--fs-nano); color: var(--fg-2); }
.chat-reactions .rxn.you .n { color: var(--accent-ink); }

.chat-typing { display: inline-flex; gap: var(--space-1); align-items: center; }
.chat-typing span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--fg-3);
}

@media (prefers-reduced-motion: no-preference) {
  .chat-typing span {
    animation: chat-typing-bounce 1.4s infinite ease-in-out;
  }
  .chat-typing span:nth-child(1) { animation-delay: 0s; }
  .chat-typing span:nth-child(2) { animation-delay: 0.18s; }
  .chat-typing span:nth-child(3) { animation-delay: 0.36s; }
  @keyframes chat-typing-bounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.55; }
    30% { transform: translateY(-5px); opacity: 1; }
  }
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes chat-fade-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
  }

  .chat-msg {
    animation: chat-fade-in 0.3s ease-out forwards;
  }
  .chat-msg:nth-child(1) { animation-delay: 0s; }
  .chat-msg:nth-child(2) { animation-delay: 0.05s; }
  .chat-msg:nth-child(3) { animation-delay: 0.1s; }
  .chat-msg:nth-child(n+4) { animation-delay: 0.15s; }
}

/* Calm composer (claude.ai/code): ONE bordered rounded-rect shell holding the
   context line, a borderless textarea, the hint, and an inline send button -
   not a stadium pill + a floating round send. The shell carries the border and
   the focus ring; the textarea fills it transparently. flex-wrap lets the
   context line and hint occupy their own rows above/below the input row. */
.chat-composer {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  background: var(--bg);
  /* The composer sits bg-on-bg: the 14% --rule hairline is ~1.3:1 on paper,
     leaving the primary input near-invisible at rest - use the strong rule. */
  border: var(--bw-hair) solid var(--rule-strong);
  border-radius: var(--r-2);
  /* A flat hairline box on a flat background is the single most-repeated
     "looks unfinished" tell in the chat surface - the one control the user
     types into every turn had no more visual weight than a settings card.
     --shadow-1 (already defined kit-wide, just unused here) lifts it a hair
     off the page at rest; the existing focus-within box-shadow overrides it. */
  box-shadow: var(--shadow-1);
  flex-shrink: 0;
  transition: border-color var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease);
}
.chat-composer:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
}
.chat-composer.is-error,
.chat-composer:has(textarea[aria-invalid="true"]) {
  border-color: var(--flame);
}
.chat-composer.is-error:focus-within,
.chat-composer:has(textarea[aria-invalid="true"]):focus-within {
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--flame) 22%, transparent);
}
.chat-composer textarea {
  flex: 1; min-width: 0; padding: var(--space-2) var(--space-1);
  background: none; color: var(--fg);
  border: none; border-radius: 0;
  font-family: inherit; font-size: var(--fs-sm);
  /* 1.5 is the value that actually renders (a later polish block used to
     re-declare it; the sizing block now states the truth). */
  line-height: 1.5; resize: none;
  min-height: 28px; max-height: 200px;
  box-sizing: border-box;
  /* Always auto, not focus-only: a capped-height composer that loses focus
     while scrolled must still show its scrollbar - otherwise once the field
     blurs there is zero cue that content exists below the fold. */
  overflow-y: auto;
  scrollbar-width: thin;
}
.chat-composer textarea::placeholder { color: var(--fg-3); }
.chat-composer textarea:focus { background: none; border: none; box-shadow: none; outline: none; }
.chat-composer .send {
  border-radius: var(--r-1);
  background: var(--accent); color: var(--accent-fg);
  border: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background var(--dur-snap, .15s) var(--ease, ease);
}
.chat-composer .send:disabled { opacity: .5; cursor: not-allowed; }
/* Ghost icon buttons in the toolbar (attach / emoji / more). Size + radius are
   owned by .chat-composer-toolbar .composer-btn in chat.css (32px / --r-1,
   44px coarse); this base rule keeps only the shared appearance. */
.composer-btn {
  background: transparent; color: var(--fg-3);
  border: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
}
.composer-btn:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
.chat-composer .send:hover { filter: brightness(0.92); }
.chat-composer .send:active { filter: brightness(0.94); }
.chat-composer .send:focus-visible,
.composer-btn:focus-visible {
  outline: var(--focus-w) solid var(--focus-color);
  outline-offset: var(--focus-offset);
}
.chat-composer .send:disabled {
  background: var(--bg-3); color: var(--fg-3); cursor: not-allowed; transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .chat-composer,
  .chat-composer textarea,
  .chat-composer .send,
  .composer-btn { transition: none; }
}

.aicat-portrait { display: inline-flex; align-items: center; gap: var(--space-2-5); padding: var(--space-1) 0; }
.aicat-face {
  /* 24px is the ICON size inside a 32px round chip — see .chat-file .glyph. */
  width: 32px; height: 32px; font-size: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in oklab, var(--mascot) 22%, var(--bg-2));
  border-radius: 50%; flex-shrink: 0;
  /* Cancels the global `pre { overflow-x: auto }`. This is a fixed 32px
     decorative chip, so the art overflowing its own box made it an
     unreachable keyboard scroll container (WCAG scrollable-region-focusable)
     rather than something a user could ever usefully scroll. */
  overflow: hidden;
}
.aicat-meta { display: flex; flex-direction: column; font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
/* --mascot-deep is now theme-tuned at the token layer (paper #B81F63 /
   ink #FF5C9E), so this needs no per-theme override. The previous
   [data-theme="dark"],[data-theme="ink"] override missed data-theme="auto"
   under OS-dark, which is how the kits actually render — the author name
   fell back to the paper tone at 3.13:1 on ink. */
.aicat-meta .name { color: var(--mascot-deep, var(--mascot)); font-weight: 600; }

